]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
Added r_shadow_bouncegrid_lightpathsize which is an alternative to blur
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 #ifdef WIN32
38 // Enable NVIDIA High Performance Graphics while using Integrated Graphics.
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
43 #ifdef __cplusplus
44 }
45 #endif
46 #endif
47
48 mempool_t *r_main_mempool;
49 rtexturepool_t *r_main_texturepool;
50
51 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
52
53 static qboolean r_loadnormalmap;
54 static qboolean r_loadgloss;
55 qboolean r_loadfog;
56 static qboolean r_loaddds;
57 static qboolean r_savedds;
58 static qboolean r_gpuskeletal;
59
60 //
61 // screen size info
62 //
63 r_refdef_t r_refdef;
64
65 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
66 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
67 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
68 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
69 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
70 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
71 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
72 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
73 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
74 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
75 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
76 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
77
78 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
79 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
80 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
81 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
82 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
83
84 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
85 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
86 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
87 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
88 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
89 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
90 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
91 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
92 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
93 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
94 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
95 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
96 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
97 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
98 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
99 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
100 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
101 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
102 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
103 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
104 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
105 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
106 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
107 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
108 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
109 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
110 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
111 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
112 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
113 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
114 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
115 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
116 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
117 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
118 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
119
120 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
121 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
122 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
123
124 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
125 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
126 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
127 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
128 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
129 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
130 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
131 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
132 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
133 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
134 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
135 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
136 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
137 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
138 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
139 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
140 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
141 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
142 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
143 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
144 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
145 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
146 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
147 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
148 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
149 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
150
151 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
152 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
153 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
154 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
155 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
156 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
157 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
158 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
159
160 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
161 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
162
163 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
164 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
165 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
166
167 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
168 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
169 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
170 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
171 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
172 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
173 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
174 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
175 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
176
177 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
178 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
179 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
180 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
181 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
182 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
183 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
184 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
185 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
186 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
187 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
188 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
189 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
190 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
191 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
192 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
193 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
194 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
195 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
196
197 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
198 cvar_t r_water_cameraentitiesonly = {CVAR_SAVE, "r_water_cameraentitiesonly", "0", "whether to only show QC-defined reflections/refractions (typically used for camera- or portal-like effects)"};
199 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
200 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
201 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
202 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
203 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
204 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
205 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
206 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
207
208 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
209 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
210 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
211 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
212
213 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
214 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
215
216 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
217 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
218 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
219 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
220 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
221 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
222
223 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
224 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
225 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
226 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
227 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
228 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
229 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
230 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
231 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
232 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
233
234 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
235
236 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
237
238 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
239
240 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
241
242 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
243 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
244 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
245 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
246
247 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
248 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
249
250 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
251
252 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
253 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
254 {
255         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
256         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
257         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
258         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
259 };
260
261 extern cvar_t v_glslgamma;
262 extern cvar_t v_glslgamma_2d;
263
264 extern qboolean v_flipped_state;
265
266 r_framebufferstate_t r_fb;
267
268 /// shadow volume bsp struct with automatically growing nodes buffer
269 svbsp_t r_svbsp;
270
271 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
272
273 rtexture_t *r_texture_blanknormalmap;
274 rtexture_t *r_texture_white;
275 rtexture_t *r_texture_grey128;
276 rtexture_t *r_texture_black;
277 rtexture_t *r_texture_notexture;
278 rtexture_t *r_texture_whitecube;
279 rtexture_t *r_texture_normalizationcube;
280 rtexture_t *r_texture_fogattenuation;
281 rtexture_t *r_texture_fogheighttexture;
282 rtexture_t *r_texture_gammaramps;
283 unsigned int r_texture_gammaramps_serial;
284 //rtexture_t *r_texture_fogintensity;
285 rtexture_t *r_texture_reflectcube;
286
287 // TODO: hash lookups?
288 typedef struct cubemapinfo_s
289 {
290         char basename[64];
291         rtexture_t *texture;
292 }
293 cubemapinfo_t;
294
295 int r_texture_numcubemaps;
296 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
297
298 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
299 unsigned int r_numqueries;
300 unsigned int r_maxqueries;
301
302 typedef struct r_qwskincache_s
303 {
304         char name[MAX_QPATH];
305         skinframe_t *skinframe;
306 }
307 r_qwskincache_t;
308
309 static r_qwskincache_t *r_qwskincache;
310 static int r_qwskincache_size;
311
312 /// vertex coordinates for a quad that covers the screen exactly
313 extern const float r_screenvertex3f[12];
314 extern const float r_d3dscreenvertex3f[12];
315 const float r_screenvertex3f[12] =
316 {
317         0, 0, 0,
318         1, 0, 0,
319         1, 1, 0,
320         0, 1, 0
321 };
322 const float r_d3dscreenvertex3f[12] =
323 {
324         0, 1, 0,
325         1, 1, 0,
326         1, 0, 0,
327         0, 0, 0
328 };
329
330 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
331 {
332         int i;
333         for (i = 0;i < verts;i++)
334         {
335                 out[0] = in[0] * r;
336                 out[1] = in[1] * g;
337                 out[2] = in[2] * b;
338                 out[3] = in[3];
339                 in += 4;
340                 out += 4;
341         }
342 }
343
344 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
345 {
346         int i;
347         for (i = 0;i < verts;i++)
348         {
349                 out[0] = r;
350                 out[1] = g;
351                 out[2] = b;
352                 out[3] = a;
353                 out += 4;
354         }
355 }
356
357 // FIXME: move this to client?
358 void FOG_clear(void)
359 {
360         if (gamemode == GAME_NEHAHRA)
361         {
362                 Cvar_Set("gl_fogenable", "0");
363                 Cvar_Set("gl_fogdensity", "0.2");
364                 Cvar_Set("gl_fogred", "0.3");
365                 Cvar_Set("gl_foggreen", "0.3");
366                 Cvar_Set("gl_fogblue", "0.3");
367         }
368         r_refdef.fog_density = 0;
369         r_refdef.fog_red = 0;
370         r_refdef.fog_green = 0;
371         r_refdef.fog_blue = 0;
372         r_refdef.fog_alpha = 1;
373         r_refdef.fog_start = 0;
374         r_refdef.fog_end = 16384;
375         r_refdef.fog_height = 1<<30;
376         r_refdef.fog_fadedepth = 128;
377         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
378 }
379
380 static void R_BuildBlankTextures(void)
381 {
382         unsigned char data[4];
383         data[2] = 128; // normal X
384         data[1] = 128; // normal Y
385         data[0] = 255; // normal Z
386         data[3] = 255; // height
387         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
388         data[0] = 255;
389         data[1] = 255;
390         data[2] = 255;
391         data[3] = 255;
392         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
393         data[0] = 128;
394         data[1] = 128;
395         data[2] = 128;
396         data[3] = 255;
397         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
398         data[0] = 0;
399         data[1] = 0;
400         data[2] = 0;
401         data[3] = 255;
402         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
403 }
404
405 static void R_BuildNoTexture(void)
406 {
407         int x, y;
408         unsigned char pix[16][16][4];
409         // this makes a light grey/dark grey checkerboard texture
410         for (y = 0;y < 16;y++)
411         {
412                 for (x = 0;x < 16;x++)
413                 {
414                         if ((y < 8) ^ (x < 8))
415                         {
416                                 pix[y][x][0] = 128;
417                                 pix[y][x][1] = 128;
418                                 pix[y][x][2] = 128;
419                                 pix[y][x][3] = 255;
420                         }
421                         else
422                         {
423                                 pix[y][x][0] = 64;
424                                 pix[y][x][1] = 64;
425                                 pix[y][x][2] = 64;
426                                 pix[y][x][3] = 255;
427                         }
428                 }
429         }
430         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
431 }
432
433 static void R_BuildWhiteCube(void)
434 {
435         unsigned char data[6*1*1*4];
436         memset(data, 255, sizeof(data));
437         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
438 }
439
440 static void R_BuildNormalizationCube(void)
441 {
442         int x, y, side;
443         vec3_t v;
444         vec_t s, t, intensity;
445 #define NORMSIZE 64
446         unsigned char *data;
447         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
448         for (side = 0;side < 6;side++)
449         {
450                 for (y = 0;y < NORMSIZE;y++)
451                 {
452                         for (x = 0;x < NORMSIZE;x++)
453                         {
454                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
455                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
456                                 switch(side)
457                                 {
458                                 default:
459                                 case 0:
460                                         v[0] = 1;
461                                         v[1] = -t;
462                                         v[2] = -s;
463                                         break;
464                                 case 1:
465                                         v[0] = -1;
466                                         v[1] = -t;
467                                         v[2] = s;
468                                         break;
469                                 case 2:
470                                         v[0] = s;
471                                         v[1] = 1;
472                                         v[2] = t;
473                                         break;
474                                 case 3:
475                                         v[0] = s;
476                                         v[1] = -1;
477                                         v[2] = -t;
478                                         break;
479                                 case 4:
480                                         v[0] = s;
481                                         v[1] = -t;
482                                         v[2] = 1;
483                                         break;
484                                 case 5:
485                                         v[0] = -s;
486                                         v[1] = -t;
487                                         v[2] = -1;
488                                         break;
489                                 }
490                                 intensity = 127.0f / sqrt(DotProduct(v, v));
491                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
492                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
493                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
494                                 data[((side*64+y)*64+x)*4+3] = 255;
495                         }
496                 }
497         }
498         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
499         Mem_Free(data);
500 }
501
502 static void R_BuildFogTexture(void)
503 {
504         int x, b;
505 #define FOGWIDTH 256
506         unsigned char data1[FOGWIDTH][4];
507         //unsigned char data2[FOGWIDTH][4];
508         double d, r, alpha;
509
510         r_refdef.fogmasktable_start = r_refdef.fog_start;
511         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
512         r_refdef.fogmasktable_range = r_refdef.fogrange;
513         r_refdef.fogmasktable_density = r_refdef.fog_density;
514
515         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
516         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
517         {
518                 d = (x * r - r_refdef.fogmasktable_start);
519                 if(developer_extra.integer)
520                         Con_DPrintf("%f ", d);
521                 d = max(0, d);
522                 if (r_fog_exp2.integer)
523                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
524                 else
525                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
526                 if(developer_extra.integer)
527                         Con_DPrintf(" : %f ", alpha);
528                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
529                 if(developer_extra.integer)
530                         Con_DPrintf(" = %f\n", alpha);
531                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
532         }
533
534         for (x = 0;x < FOGWIDTH;x++)
535         {
536                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
537                 data1[x][0] = b;
538                 data1[x][1] = b;
539                 data1[x][2] = b;
540                 data1[x][3] = 255;
541                 //data2[x][0] = 255 - b;
542                 //data2[x][1] = 255 - b;
543                 //data2[x][2] = 255 - b;
544                 //data2[x][3] = 255;
545         }
546         if (r_texture_fogattenuation)
547         {
548                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
549                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
550         }
551         else
552         {
553                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
554                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
555         }
556 }
557
558 static void R_BuildFogHeightTexture(void)
559 {
560         unsigned char *inpixels;
561         int size;
562         int x;
563         int y;
564         int j;
565         float c[4];
566         float f;
567         inpixels = NULL;
568         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
569         if (r_refdef.fogheighttexturename[0])
570                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
571         if (!inpixels)
572         {
573                 r_refdef.fog_height_tablesize = 0;
574                 if (r_texture_fogheighttexture)
575                         R_FreeTexture(r_texture_fogheighttexture);
576                 r_texture_fogheighttexture = NULL;
577                 if (r_refdef.fog_height_table2d)
578                         Mem_Free(r_refdef.fog_height_table2d);
579                 r_refdef.fog_height_table2d = NULL;
580                 if (r_refdef.fog_height_table1d)
581                         Mem_Free(r_refdef.fog_height_table1d);
582                 r_refdef.fog_height_table1d = NULL;
583                 return;
584         }
585         size = image_width;
586         r_refdef.fog_height_tablesize = size;
587         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
588         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
589         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
590         Mem_Free(inpixels);
591         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
592         // average fog color table accounting for every fog layer between a point
593         // and the camera.  (Note: attenuation is handled separately!)
594         for (y = 0;y < size;y++)
595         {
596                 for (x = 0;x < size;x++)
597                 {
598                         Vector4Clear(c);
599                         f = 0;
600                         if (x < y)
601                         {
602                                 for (j = x;j <= y;j++)
603                                 {
604                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
605                                         f++;
606                                 }
607                         }
608                         else
609                         {
610                                 for (j = x;j >= y;j--)
611                                 {
612                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
613                                         f++;
614                                 }
615                         }
616                         f = 1.0f / f;
617                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
618                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
619                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
620                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
621                 }
622         }
623         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
624 }
625
626 //=======================================================================================================================================================
627
628 static const char *builtinshaderstrings[] =
629 {
630 #include "shader_glsl.h"
631 0
632 };
633
634 const char *builtinhlslshaderstrings[] =
635 {
636 #include "shader_hlsl.h"
637 0
638 };
639
640 char *glslshaderstring = NULL;
641 char *hlslshaderstring = NULL;
642
643 //=======================================================================================================================================================
644
645 typedef struct shaderpermutationinfo_s
646 {
647         const char *pretext;
648         const char *name;
649 }
650 shaderpermutationinfo_t;
651
652 typedef struct shadermodeinfo_s
653 {
654         const char *filename;
655         const char *pretext;
656         const char *name;
657 }
658 shadermodeinfo_t;
659
660 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
661 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
662 {
663         {"#define USEDIFFUSE\n", " diffuse"},
664         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
665         {"#define USEVIEWTINT\n", " viewtint"},
666         {"#define USECOLORMAPPING\n", " colormapping"},
667         {"#define USESATURATION\n", " saturation"},
668         {"#define USEFOGINSIDE\n", " foginside"},
669         {"#define USEFOGOUTSIDE\n", " fogoutside"},
670         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
671         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
672         {"#define USEGAMMARAMPS\n", " gammaramps"},
673         {"#define USECUBEFILTER\n", " cubefilter"},
674         {"#define USEGLOW\n", " glow"},
675         {"#define USEBLOOM\n", " bloom"},
676         {"#define USESPECULAR\n", " specular"},
677         {"#define USEPOSTPROCESSING\n", " postprocessing"},
678         {"#define USEREFLECTION\n", " reflection"},
679         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
680         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
681         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
682         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
683         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
684         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
685         {"#define USEALPHAKILL\n", " alphakill"},
686         {"#define USEREFLECTCUBE\n", " reflectcube"},
687         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
688         {"#define USEBOUNCEGRID\n", " bouncegrid"},
689         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
690         {"#define USETRIPPY\n", " trippy"},
691         {"#define USEDEPTHRGB\n", " depthrgb"},
692         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
693         {"#define USESKELETAL\n", " skeletal"},
694         {"#define USEOCCLUDE\n", " occlude"}
695 };
696
697 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
698 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
699 {
700         {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
701         {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
702         {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
703         {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
704         {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
705         {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
706         {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
707         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
708         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
709         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
710         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
711         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
712         {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
713         {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
714         {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
715         {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
716         {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
717 };
718
719 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
720 {
721         {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
722         {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
723         {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
724         {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
725         {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
726         {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
727         {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
728         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
729         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
730         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
731         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
732         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
733         {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
734         {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
735         {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
736         {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
737         {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
738 };
739
740 struct r_glsl_permutation_s;
741 typedef struct r_glsl_permutation_s
742 {
743         /// hash lookup data
744         struct r_glsl_permutation_s *hashnext;
745         unsigned int mode;
746         unsigned int permutation;
747
748         /// indicates if we have tried compiling this permutation already
749         qboolean compiled;
750         /// 0 if compilation failed
751         int program;
752         // texture units assigned to each detected uniform
753         int tex_Texture_First;
754         int tex_Texture_Second;
755         int tex_Texture_GammaRamps;
756         int tex_Texture_Normal;
757         int tex_Texture_Color;
758         int tex_Texture_Gloss;
759         int tex_Texture_Glow;
760         int tex_Texture_SecondaryNormal;
761         int tex_Texture_SecondaryColor;
762         int tex_Texture_SecondaryGloss;
763         int tex_Texture_SecondaryGlow;
764         int tex_Texture_Pants;
765         int tex_Texture_Shirt;
766         int tex_Texture_FogHeightTexture;
767         int tex_Texture_FogMask;
768         int tex_Texture_Lightmap;
769         int tex_Texture_Deluxemap;
770         int tex_Texture_Attenuation;
771         int tex_Texture_Cube;
772         int tex_Texture_Refraction;
773         int tex_Texture_Reflection;
774         int tex_Texture_ShadowMap2D;
775         int tex_Texture_CubeProjection;
776         int tex_Texture_ScreenNormalMap;
777         int tex_Texture_ScreenDiffuse;
778         int tex_Texture_ScreenSpecular;
779         int tex_Texture_ReflectMask;
780         int tex_Texture_ReflectCube;
781         int tex_Texture_BounceGrid;
782         /// locations of detected uniforms in program object, or -1 if not found
783         int loc_Texture_First;
784         int loc_Texture_Second;
785         int loc_Texture_GammaRamps;
786         int loc_Texture_Normal;
787         int loc_Texture_Color;
788         int loc_Texture_Gloss;
789         int loc_Texture_Glow;
790         int loc_Texture_SecondaryNormal;
791         int loc_Texture_SecondaryColor;
792         int loc_Texture_SecondaryGloss;
793         int loc_Texture_SecondaryGlow;
794         int loc_Texture_Pants;
795         int loc_Texture_Shirt;
796         int loc_Texture_FogHeightTexture;
797         int loc_Texture_FogMask;
798         int loc_Texture_Lightmap;
799         int loc_Texture_Deluxemap;
800         int loc_Texture_Attenuation;
801         int loc_Texture_Cube;
802         int loc_Texture_Refraction;
803         int loc_Texture_Reflection;
804         int loc_Texture_ShadowMap2D;
805         int loc_Texture_CubeProjection;
806         int loc_Texture_ScreenNormalMap;
807         int loc_Texture_ScreenDiffuse;
808         int loc_Texture_ScreenSpecular;
809         int loc_Texture_ReflectMask;
810         int loc_Texture_ReflectCube;
811         int loc_Texture_BounceGrid;
812         int loc_Alpha;
813         int loc_BloomBlur_Parameters;
814         int loc_ClientTime;
815         int loc_Color_Ambient;
816         int loc_Color_Diffuse;
817         int loc_Color_Specular;
818         int loc_Color_Glow;
819         int loc_Color_Pants;
820         int loc_Color_Shirt;
821         int loc_DeferredColor_Ambient;
822         int loc_DeferredColor_Diffuse;
823         int loc_DeferredColor_Specular;
824         int loc_DeferredMod_Diffuse;
825         int loc_DeferredMod_Specular;
826         int loc_DistortScaleRefractReflect;
827         int loc_EyePosition;
828         int loc_FogColor;
829         int loc_FogHeightFade;
830         int loc_FogPlane;
831         int loc_FogPlaneViewDist;
832         int loc_FogRangeRecip;
833         int loc_LightColor;
834         int loc_LightDir;
835         int loc_LightPosition;
836         int loc_OffsetMapping_ScaleSteps;
837         int loc_OffsetMapping_LodDistance;
838         int loc_OffsetMapping_Bias;
839         int loc_PixelSize;
840         int loc_ReflectColor;
841         int loc_ReflectFactor;
842         int loc_ReflectOffset;
843         int loc_RefractColor;
844         int loc_Saturation;
845         int loc_ScreenCenterRefractReflect;
846         int loc_ScreenScaleRefractReflect;
847         int loc_ScreenToDepth;
848         int loc_ShadowMap_Parameters;
849         int loc_ShadowMap_TextureScale;
850         int loc_SpecularPower;
851         int loc_Skeletal_Transform12;
852         int loc_UserVec1;
853         int loc_UserVec2;
854         int loc_UserVec3;
855         int loc_UserVec4;
856         int loc_ViewTintColor;
857         int loc_ViewToLight;
858         int loc_ModelToLight;
859         int loc_TexMatrix;
860         int loc_BackgroundTexMatrix;
861         int loc_ModelViewProjectionMatrix;
862         int loc_ModelViewMatrix;
863         int loc_PixelToScreenTexCoord;
864         int loc_ModelToReflectCube;
865         int loc_ShadowMapMatrix;
866         int loc_BloomColorSubtract;
867         int loc_NormalmapScrollBlend;
868         int loc_BounceGridMatrix;
869         int loc_BounceGridIntensity;
870         /// uniform block bindings
871         int ubibind_Skeletal_Transform12_UniformBlock;
872         /// uniform block indices
873         int ubiloc_Skeletal_Transform12_UniformBlock;
874 }
875 r_glsl_permutation_t;
876
877 #define SHADERPERMUTATION_HASHSIZE 256
878
879
880 // non-degradable "lightweight" shader parameters to keep the permutations simpler
881 // these can NOT degrade! only use for simple stuff
882 enum
883 {
884         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
885         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
886         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
887         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
888         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
889         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
890         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
891         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
892         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
893         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
894         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
895         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
896         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
897         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
898 };
899 #define SHADERSTATICPARMS_COUNT 14
900
901 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
902 static int shaderstaticparms_count = 0;
903
904 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
905 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
906
907 extern qboolean r_shadow_shadowmapsampler;
908 extern int r_shadow_shadowmappcf;
909 qboolean R_CompileShader_CheckStaticParms(void)
910 {
911         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
912         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
913         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
914
915         // detect all
916         if (r_glsl_saturation_redcompensate.integer)
917                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
918         if (r_glsl_vertextextureblend_usebothalphas.integer)
919                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
920         if (r_shadow_glossexact.integer)
921                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
922         if (r_glsl_postprocess.integer)
923         {
924                 if (r_glsl_postprocess_uservec1_enable.integer)
925                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
926                 if (r_glsl_postprocess_uservec2_enable.integer)
927                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
928                 if (r_glsl_postprocess_uservec3_enable.integer)
929                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
930                 if (r_glsl_postprocess_uservec4_enable.integer)
931                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
932         }
933         if (r_fxaa.integer)
934                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
935         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
936                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
937
938         if (r_shadow_shadowmapsampler)
939                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
940         if (r_shadow_shadowmappcf > 1)
941                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
942         else if (r_shadow_shadowmappcf)
943                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
944         if (r_celshading.integer)
945                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
946         if (r_celoutlines.integer)
947                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
948
949         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
950 }
951
952 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
953         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
954                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
955         else \
956                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
957 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
958 {
959         shaderstaticparms_count = 0;
960
961         // emit all
962         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
963         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
964         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
965         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
966         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
967         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
968         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
969         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
970         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
971         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
972         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
973         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
974         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
975         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
976 }
977
978 /// information about each possible shader permutation
979 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
980 /// currently selected permutation
981 r_glsl_permutation_t *r_glsl_permutation;
982 /// storage for permutations linked in the hash table
983 memexpandablearray_t r_glsl_permutationarray;
984
985 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
986 {
987         //unsigned int hashdepth = 0;
988         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
989         r_glsl_permutation_t *p;
990         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
991         {
992                 if (p->mode == mode && p->permutation == permutation)
993                 {
994                         //if (hashdepth > 10)
995                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
996                         return p;
997                 }
998                 //hashdepth++;
999         }
1000         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
1001         p->mode = mode;
1002         p->permutation = permutation;
1003         p->hashnext = r_glsl_permutationhash[mode][hashindex];
1004         r_glsl_permutationhash[mode][hashindex] = p;
1005         //if (hashdepth > 10)
1006         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1007         return p;
1008 }
1009
1010 static char *R_ShaderStrCat(const char **strings)
1011 {
1012         char *string, *s;
1013         const char **p = strings;
1014         const char *t;
1015         size_t len = 0;
1016         for (p = strings;(t = *p);p++)
1017                 len += strlen(t);
1018         len++;
1019         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1020         len = 0;
1021         for (p = strings;(t = *p);p++)
1022         {
1023                 len = strlen(t);
1024                 memcpy(s, t, len);
1025                 s += len;
1026         }
1027         *s = 0;
1028         return string;
1029 }
1030
1031 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1032 {
1033         char *shaderstring;
1034         if (!filename || !filename[0])
1035                 return NULL;
1036         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1037         if (!strcmp(filename, "glsl/default.glsl"))
1038         {
1039                 if (builtinonly)
1040                         return R_ShaderStrCat(builtinshaderstrings);
1041                 if (!glslshaderstring)
1042                 {
1043                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1044                         if (glslshaderstring)
1045                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1046                         else
1047                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1048                 }
1049                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1050                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1051                 return shaderstring;
1052         }
1053         if (!strcmp(filename, "hlsl/default.hlsl"))
1054         {
1055                 if (builtinonly)
1056                         return R_ShaderStrCat(builtinhlslshaderstrings);
1057                 if (!hlslshaderstring)
1058                 {
1059                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1060                         if (hlslshaderstring)
1061                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1062                         else
1063                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1064                 }
1065                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1066                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1067                 return shaderstring;
1068         }
1069         // we don't have builtin strings for any other files
1070         if (builtinonly)
1071                 return NULL;
1072         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1073         if (shaderstring)
1074         {
1075                 if (printfromdisknotice)
1076                         Con_DPrintf("from disk %s... ", filename);
1077                 return shaderstring;
1078         }
1079         return shaderstring;
1080 }
1081
1082 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1083 {
1084         int i;
1085         int ubibind;
1086         int sampler;
1087         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1088         char *sourcestring;
1089         char permutationname[256];
1090         int vertstrings_count = 0;
1091         int geomstrings_count = 0;
1092         int fragstrings_count = 0;
1093         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1094         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1095         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1096
1097         if (p->compiled)
1098                 return;
1099         p->compiled = true;
1100         p->program = 0;
1101
1102         permutationname[0] = 0;
1103         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1104
1105         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1106
1107         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1108         if(vid.support.glshaderversion >= 140)
1109         {
1110                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1111                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1112                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1113                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1114                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1115                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1116         }
1117         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1118         else if(vid.support.glshaderversion >= 130)
1119         {
1120                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1121                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1122                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1123                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1124                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1125                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1126         }
1127
1128         // the first pretext is which type of shader to compile as
1129         // (later these will all be bound together as a program object)
1130         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1131         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1132         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1133
1134         // the second pretext is the mode (for example a light source)
1135         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1136         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1137         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1138         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1139
1140         // now add all the permutation pretexts
1141         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1142         {
1143                 if (permutation & (1<<i))
1144                 {
1145                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1146                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1147                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1148                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1149                 }
1150                 else
1151                 {
1152                         // keep line numbers correct
1153                         vertstrings_list[vertstrings_count++] = "\n";
1154                         geomstrings_list[geomstrings_count++] = "\n";
1155                         fragstrings_list[fragstrings_count++] = "\n";
1156                 }
1157         }
1158
1159         // add static parms
1160         R_CompileShader_AddStaticParms(mode, permutation);
1161         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1162         vertstrings_count += shaderstaticparms_count;
1163         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1164         geomstrings_count += shaderstaticparms_count;
1165         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1166         fragstrings_count += shaderstaticparms_count;
1167
1168         // now append the shader text itself
1169         vertstrings_list[vertstrings_count++] = sourcestring;
1170         geomstrings_list[geomstrings_count++] = sourcestring;
1171         fragstrings_list[fragstrings_count++] = sourcestring;
1172
1173         // compile the shader program
1174         if (vertstrings_count + geomstrings_count + fragstrings_count)
1175                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1176         if (p->program)
1177         {
1178                 CHECKGLERROR
1179                 qglUseProgram(p->program);CHECKGLERROR
1180                 // look up all the uniform variable names we care about, so we don't
1181                 // have to look them up every time we set them
1182
1183 #if 0
1184                 // debugging aid
1185                 {
1186                         GLint activeuniformindex = 0;
1187                         GLint numactiveuniforms = 0;
1188                         char uniformname[128];
1189                         GLsizei uniformnamelength = 0;
1190                         GLint uniformsize = 0;
1191                         GLenum uniformtype = 0;
1192                         memset(uniformname, 0, sizeof(uniformname));
1193                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1194                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1195                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1196                         {
1197                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1198                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1199                         }
1200                 }
1201 #endif
1202
1203                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1204                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1205                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1206                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1207                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1208                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1209                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1210                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1211                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1212                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1213                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1214                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1215                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1216                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1217                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1218                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1219                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1220                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1221                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1222                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1223                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1224                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1225                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1226                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1227                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1228                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1229                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1230                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1231                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1232                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1233                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1234                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1235                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1236                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1237                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1238                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1239                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1240                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1241                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1242                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1243                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1244                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1245                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1246                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1247                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1248                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1249                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1250                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1251                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1252                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1253                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1254                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1255                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1256                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1257                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1258                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1259                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1260                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1261                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1262                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1263                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1264                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1265                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1266                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1267                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1268                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1269                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1270                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1271                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1272                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1273                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1274                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1275                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1276                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1277                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1278                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1279                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1280                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1281                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1282                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1283                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1284                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1285                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1286                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1287                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1288                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1289                 // initialize the samplers to refer to the texture units we use
1290                 p->tex_Texture_First = -1;
1291                 p->tex_Texture_Second = -1;
1292                 p->tex_Texture_GammaRamps = -1;
1293                 p->tex_Texture_Normal = -1;
1294                 p->tex_Texture_Color = -1;
1295                 p->tex_Texture_Gloss = -1;
1296                 p->tex_Texture_Glow = -1;
1297                 p->tex_Texture_SecondaryNormal = -1;
1298                 p->tex_Texture_SecondaryColor = -1;
1299                 p->tex_Texture_SecondaryGloss = -1;
1300                 p->tex_Texture_SecondaryGlow = -1;
1301                 p->tex_Texture_Pants = -1;
1302                 p->tex_Texture_Shirt = -1;
1303                 p->tex_Texture_FogHeightTexture = -1;
1304                 p->tex_Texture_FogMask = -1;
1305                 p->tex_Texture_Lightmap = -1;
1306                 p->tex_Texture_Deluxemap = -1;
1307                 p->tex_Texture_Attenuation = -1;
1308                 p->tex_Texture_Cube = -1;
1309                 p->tex_Texture_Refraction = -1;
1310                 p->tex_Texture_Reflection = -1;
1311                 p->tex_Texture_ShadowMap2D = -1;
1312                 p->tex_Texture_CubeProjection = -1;
1313                 p->tex_Texture_ScreenNormalMap = -1;
1314                 p->tex_Texture_ScreenDiffuse = -1;
1315                 p->tex_Texture_ScreenSpecular = -1;
1316                 p->tex_Texture_ReflectMask = -1;
1317                 p->tex_Texture_ReflectCube = -1;
1318                 p->tex_Texture_BounceGrid = -1;
1319                 // bind the texture samplers in use
1320                 sampler = 0;
1321                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1322                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1323                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1324                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1325                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1326                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1327                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1328                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1329                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1330                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1331                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1332                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1333                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1334                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1335                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1336                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1337                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1338                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1339                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1340                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1341                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1342                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1343                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1344                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1345                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1346                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1347                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1348                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1349                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1350                 // get the uniform block indices so we can bind them
1351 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1352                 if (vid.support.arb_uniform_buffer_object)
1353                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1354                 else
1355 #endif
1356                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1357                 // clear the uniform block bindings
1358                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1359                 // bind the uniform blocks in use
1360                 ubibind = 0;
1361 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1362                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1363 #endif
1364                 // we're done compiling and setting up the shader, at least until it is used
1365                 CHECKGLERROR
1366                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1367         }
1368         else
1369                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1370
1371         // free the strings
1372         if (sourcestring)
1373                 Mem_Free(sourcestring);
1374 }
1375
1376 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1377 {
1378         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1379         if (r_glsl_permutation != perm)
1380         {
1381                 r_glsl_permutation = perm;
1382                 if (!r_glsl_permutation->program)
1383                 {
1384                         if (!r_glsl_permutation->compiled)
1385                         {
1386                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1387                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1388                         }
1389                         if (!r_glsl_permutation->program)
1390                         {
1391                                 // remove features until we find a valid permutation
1392                                 int i;
1393                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1394                                 {
1395                                         // reduce i more quickly whenever it would not remove any bits
1396                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1397                                         if (!(permutation & j))
1398                                                 continue;
1399                                         permutation -= j;
1400                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1401                                         if (!r_glsl_permutation->compiled)
1402                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1403                                         if (r_glsl_permutation->program)
1404                                                 break;
1405                                 }
1406                                 if (i >= SHADERPERMUTATION_COUNT)
1407                                 {
1408                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1409                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1410                                         qglUseProgram(0);CHECKGLERROR
1411                                         return; // no bit left to clear, entire mode is broken
1412                                 }
1413                         }
1414                 }
1415                 CHECKGLERROR
1416                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1417         }
1418         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1419         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1420         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1421         CHECKGLERROR
1422 }
1423
1424 #ifdef SUPPORTD3D
1425
1426 #ifdef SUPPORTD3D
1427 #include <d3d9.h>
1428 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1429 extern D3DCAPS9 vid_d3d9caps;
1430 #endif
1431
1432 struct r_hlsl_permutation_s;
1433 typedef struct r_hlsl_permutation_s
1434 {
1435         /// hash lookup data
1436         struct r_hlsl_permutation_s *hashnext;
1437         unsigned int mode;
1438         unsigned int permutation;
1439
1440         /// indicates if we have tried compiling this permutation already
1441         qboolean compiled;
1442         /// NULL if compilation failed
1443         IDirect3DVertexShader9 *vertexshader;
1444         IDirect3DPixelShader9 *pixelshader;
1445 }
1446 r_hlsl_permutation_t;
1447
1448 typedef enum D3DVSREGISTER_e
1449 {
1450         D3DVSREGISTER_TexMatrix = 0, // float4x4
1451         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1452         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1453         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1454         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1455         D3DVSREGISTER_ModelToLight = 20, // float4x4
1456         D3DVSREGISTER_EyePosition = 24,
1457         D3DVSREGISTER_FogPlane = 25,
1458         D3DVSREGISTER_LightDir = 26,
1459         D3DVSREGISTER_LightPosition = 27,
1460 }
1461 D3DVSREGISTER_t;
1462
1463 typedef enum D3DPSREGISTER_e
1464 {
1465         D3DPSREGISTER_Alpha = 0,
1466         D3DPSREGISTER_BloomBlur_Parameters = 1,
1467         D3DPSREGISTER_ClientTime = 2,
1468         D3DPSREGISTER_Color_Ambient = 3,
1469         D3DPSREGISTER_Color_Diffuse = 4,
1470         D3DPSREGISTER_Color_Specular = 5,
1471         D3DPSREGISTER_Color_Glow = 6,
1472         D3DPSREGISTER_Color_Pants = 7,
1473         D3DPSREGISTER_Color_Shirt = 8,
1474         D3DPSREGISTER_DeferredColor_Ambient = 9,
1475         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1476         D3DPSREGISTER_DeferredColor_Specular = 11,
1477         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1478         D3DPSREGISTER_DeferredMod_Specular = 13,
1479         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1480         D3DPSREGISTER_EyePosition = 15, // unused
1481         D3DPSREGISTER_FogColor = 16,
1482         D3DPSREGISTER_FogHeightFade = 17,
1483         D3DPSREGISTER_FogPlane = 18,
1484         D3DPSREGISTER_FogPlaneViewDist = 19,
1485         D3DPSREGISTER_FogRangeRecip = 20,
1486         D3DPSREGISTER_LightColor = 21,
1487         D3DPSREGISTER_LightDir = 22, // unused
1488         D3DPSREGISTER_LightPosition = 23,
1489         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1490         D3DPSREGISTER_PixelSize = 25,
1491         D3DPSREGISTER_ReflectColor = 26,
1492         D3DPSREGISTER_ReflectFactor = 27,
1493         D3DPSREGISTER_ReflectOffset = 28,
1494         D3DPSREGISTER_RefractColor = 29,
1495         D3DPSREGISTER_Saturation = 30,
1496         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1497         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1498         D3DPSREGISTER_ScreenToDepth = 33,
1499         D3DPSREGISTER_ShadowMap_Parameters = 34,
1500         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1501         D3DPSREGISTER_SpecularPower = 36,
1502         D3DPSREGISTER_UserVec1 = 37,
1503         D3DPSREGISTER_UserVec2 = 38,
1504         D3DPSREGISTER_UserVec3 = 39,
1505         D3DPSREGISTER_UserVec4 = 40,
1506         D3DPSREGISTER_ViewTintColor = 41,
1507         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1508         D3DPSREGISTER_BloomColorSubtract = 43,
1509         D3DPSREGISTER_ViewToLight = 44, // float4x4
1510         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1511         D3DPSREGISTER_NormalmapScrollBlend = 52,
1512         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1513         D3DPSREGISTER_OffsetMapping_Bias = 54,
1514         // next at 54
1515 }
1516 D3DPSREGISTER_t;
1517
1518 /// information about each possible shader permutation
1519 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1520 /// currently selected permutation
1521 r_hlsl_permutation_t *r_hlsl_permutation;
1522 /// storage for permutations linked in the hash table
1523 memexpandablearray_t r_hlsl_permutationarray;
1524
1525 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1526 {
1527         //unsigned int hashdepth = 0;
1528         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1529         r_hlsl_permutation_t *p;
1530         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1531         {
1532                 if (p->mode == mode && p->permutation == permutation)
1533                 {
1534                         //if (hashdepth > 10)
1535                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1536                         return p;
1537                 }
1538                 //hashdepth++;
1539         }
1540         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1541         p->mode = mode;
1542         p->permutation = permutation;
1543         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1544         r_hlsl_permutationhash[mode][hashindex] = p;
1545         //if (hashdepth > 10)
1546         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1547         return p;
1548 }
1549
1550 #include <d3dx9.h>
1551 //#include <d3dx9shader.h>
1552 //#include <d3dx9mesh.h>
1553
1554 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1555 {
1556         DWORD *vsbin = NULL;
1557         DWORD *psbin = NULL;
1558         fs_offset_t vsbinsize;
1559         fs_offset_t psbinsize;
1560 //      IDirect3DVertexShader9 *vs = NULL;
1561 //      IDirect3DPixelShader9 *ps = NULL;
1562         ID3DXBuffer *vslog = NULL;
1563         ID3DXBuffer *vsbuffer = NULL;
1564         ID3DXConstantTable *vsconstanttable = NULL;
1565         ID3DXBuffer *pslog = NULL;
1566         ID3DXBuffer *psbuffer = NULL;
1567         ID3DXConstantTable *psconstanttable = NULL;
1568         int vsresult = 0;
1569         int psresult = 0;
1570         char temp[MAX_INPUTLINE];
1571         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1572         char vabuf[1024];
1573         qboolean debugshader = gl_paranoid.integer != 0;
1574         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1575         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1576         if (!debugshader)
1577         {
1578                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1579                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1580         }
1581         if ((!vsbin && vertstring) || (!psbin && fragstring))
1582         {
1583                 const char* dllnames_d3dx9 [] =
1584                 {
1585                         "d3dx9_43.dll",
1586                         "d3dx9_42.dll",
1587                         "d3dx9_41.dll",
1588                         "d3dx9_40.dll",
1589                         "d3dx9_39.dll",
1590                         "d3dx9_38.dll",
1591                         "d3dx9_37.dll",
1592                         "d3dx9_36.dll",
1593                         "d3dx9_35.dll",
1594                         "d3dx9_34.dll",
1595                         "d3dx9_33.dll",
1596                         "d3dx9_32.dll",
1597                         "d3dx9_31.dll",
1598                         "d3dx9_30.dll",
1599                         "d3dx9_29.dll",
1600                         "d3dx9_28.dll",
1601                         "d3dx9_27.dll",
1602                         "d3dx9_26.dll",
1603                         "d3dx9_25.dll",
1604                         "d3dx9_24.dll",
1605                         NULL
1606                 };
1607                 dllhandle_t d3dx9_dll = NULL;
1608                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1609                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1610                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1611                 dllfunction_t d3dx9_dllfuncs[] =
1612                 {
1613                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1614                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1615                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1616                         {NULL, NULL}
1617                 };
1618                 // LordHavoc: the June 2010 SDK lacks these macros to make ID3DXBuffer usable in C, and to make it work in both C and C++ the macros are needed...
1619 #ifndef ID3DXBuffer_GetBufferPointer
1620 #if !defined(__cplusplus) || defined(CINTERFACE)
1621 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1622 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1623 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1624 #else
1625 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1626 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1627 #define ID3DXBuffer_Release(p)            (p)->Release()
1628 #endif
1629 #endif
1630                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1631                 {
1632                         DWORD shaderflags = 0;
1633                         if (debugshader)
1634                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1635                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1636                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1637                         if (vertstring && vertstring[0])
1638                         {
1639                                 if (debugshader)
1640                                 {
1641                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1642                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1643                                 }
1644                                 else
1645                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1646                                 if (vsbuffer)
1647                                 {
1648                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1649                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1650                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1651                                         ID3DXBuffer_Release(vsbuffer);
1652                                 }
1653                                 if (vslog)
1654                                 {
1655                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1656                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1657                                         ID3DXBuffer_Release(vslog);
1658                                 }
1659                         }
1660                         if (fragstring && fragstring[0])
1661                         {
1662                                 if (debugshader)
1663                                 {
1664                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1665                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1666                                 }
1667                                 else
1668                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1669                                 if (psbuffer)
1670                                 {
1671                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1672                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1673                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1674                                         ID3DXBuffer_Release(psbuffer);
1675                                 }
1676                                 if (pslog)
1677                                 {
1678                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1679                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1680                                         ID3DXBuffer_Release(pslog);
1681                                 }
1682                         }
1683                         Sys_UnloadLibrary(&d3dx9_dll);
1684                 }
1685                 else
1686                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1687         }
1688         if (vsbin && psbin)
1689         {
1690                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1691                 if (FAILED(vsresult))
1692                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1693                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1694                 if (FAILED(psresult))
1695                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1696         }
1697         // free the shader data
1698         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1699         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1700 }
1701
1702 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1703 {
1704         int i;
1705         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1706         int vertstring_length = 0;
1707         int geomstring_length = 0;
1708         int fragstring_length = 0;
1709         char *t;
1710         char *sourcestring;
1711         char *vertstring, *geomstring, *fragstring;
1712         char permutationname[256];
1713         char cachename[256];
1714         int vertstrings_count = 0;
1715         int geomstrings_count = 0;
1716         int fragstrings_count = 0;
1717         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1718         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1719         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1720
1721         if (p->compiled)
1722                 return;
1723         p->compiled = true;
1724         p->vertexshader = NULL;
1725         p->pixelshader = NULL;
1726
1727         permutationname[0] = 0;
1728         cachename[0] = 0;
1729         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1730
1731         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1732         strlcat(cachename, "hlsl/", sizeof(cachename));
1733
1734         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1735         vertstrings_count = 0;
1736         geomstrings_count = 0;
1737         fragstrings_count = 0;
1738         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1739         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1740         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1741
1742         // the first pretext is which type of shader to compile as
1743         // (later these will all be bound together as a program object)
1744         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1745         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1746         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1747
1748         // the second pretext is the mode (for example a light source)
1749         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1750         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1751         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1752         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1753         strlcat(cachename, modeinfo->name, sizeof(cachename));
1754
1755         // now add all the permutation pretexts
1756         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1757         {
1758                 if (permutation & (1<<i))
1759                 {
1760                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1761                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1762                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1763                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1764                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1765                 }
1766                 else
1767                 {
1768                         // keep line numbers correct
1769                         vertstrings_list[vertstrings_count++] = "\n";
1770                         geomstrings_list[geomstrings_count++] = "\n";
1771                         fragstrings_list[fragstrings_count++] = "\n";
1772                 }
1773         }
1774
1775         // add static parms
1776         R_CompileShader_AddStaticParms(mode, permutation);
1777         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1778         vertstrings_count += shaderstaticparms_count;
1779         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1780         geomstrings_count += shaderstaticparms_count;
1781         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1782         fragstrings_count += shaderstaticparms_count;
1783
1784         // replace spaces in the cachename with _ characters
1785         for (i = 0;cachename[i];i++)
1786                 if (cachename[i] == ' ')
1787                         cachename[i] = '_';
1788
1789         // now append the shader text itself
1790         vertstrings_list[vertstrings_count++] = sourcestring;
1791         geomstrings_list[geomstrings_count++] = sourcestring;
1792         fragstrings_list[fragstrings_count++] = sourcestring;
1793
1794         vertstring_length = 0;
1795         for (i = 0;i < vertstrings_count;i++)
1796                 vertstring_length += (int)strlen(vertstrings_list[i]);
1797         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1798         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1799                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1800
1801         geomstring_length = 0;
1802         for (i = 0;i < geomstrings_count;i++)
1803                 geomstring_length += (int)strlen(geomstrings_list[i]);
1804         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1805         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1806                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1807
1808         fragstring_length = 0;
1809         for (i = 0;i < fragstrings_count;i++)
1810                 fragstring_length += (int)strlen(fragstrings_list[i]);
1811         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1812         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1813                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1814
1815         // try to load the cached shader, or generate one
1816         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1817
1818         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1819                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1820         else
1821                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1822
1823         // free the strings
1824         if (vertstring)
1825                 Mem_Free(vertstring);
1826         if (geomstring)
1827                 Mem_Free(geomstring);
1828         if (fragstring)
1829                 Mem_Free(fragstring);
1830         if (sourcestring)
1831                 Mem_Free(sourcestring);
1832 }
1833
1834 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1835 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1836 static inline void hlslVSSetParameter4f(D3DVSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1837 static inline void hlslVSSetParameter3f(D3DVSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1838 static inline void hlslVSSetParameter2f(D3DVSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1839 static inline void hlslVSSetParameter1f(D3DVSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, temp, 1);}
1840
1841 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1842 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1843 static inline void hlslPSSetParameter4f(D3DPSREGISTER_t r, float x, float y, float z, float w) {float temp[4];Vector4Set(temp, x, y, z, w);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1844 static inline void hlslPSSetParameter3f(D3DPSREGISTER_t r, float x, float y, float z) {float temp[4];Vector4Set(temp, x, y, z, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1845 static inline void hlslPSSetParameter2f(D3DPSREGISTER_t r, float x, float y) {float temp[4];Vector4Set(temp, x, y, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1846 static inline void hlslPSSetParameter1f(D3DPSREGISTER_t r, float x) {float temp[4];Vector4Set(temp, x, 0, 0, 0);IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, temp, 1);}
1847
1848 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1849 {
1850         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1851         if (r_hlsl_permutation != perm)
1852         {
1853                 r_hlsl_permutation = perm;
1854                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1855                 {
1856                         if (!r_hlsl_permutation->compiled)
1857                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1858                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1859                         {
1860                                 // remove features until we find a valid permutation
1861                                 int i;
1862                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1863                                 {
1864                                         // reduce i more quickly whenever it would not remove any bits
1865                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1866                                         if (!(permutation & j))
1867                                                 continue;
1868                                         permutation -= j;
1869                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1870                                         if (!r_hlsl_permutation->compiled)
1871                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1872                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1873                                                 break;
1874                                 }
1875                                 if (i >= SHADERPERMUTATION_COUNT)
1876                                 {
1877                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1878                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1879                                         return; // no bit left to clear, entire mode is broken
1880                                 }
1881                         }
1882                 }
1883                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1884                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1885         }
1886         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1887         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1888         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1889 }
1890 #endif
1891
1892 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1893 {
1894         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1895         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1896         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1897         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1898 }
1899
1900 void R_GLSL_Restart_f(void)
1901 {
1902         unsigned int i, limit;
1903         if (glslshaderstring)
1904                 Mem_Free(glslshaderstring);
1905         glslshaderstring = NULL;
1906         if (hlslshaderstring)
1907                 Mem_Free(hlslshaderstring);
1908         hlslshaderstring = NULL;
1909         switch(vid.renderpath)
1910         {
1911         case RENDERPATH_D3D9:
1912 #ifdef SUPPORTD3D
1913                 {
1914                         r_hlsl_permutation_t *p;
1915                         r_hlsl_permutation = NULL;
1916                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1917                         for (i = 0;i < limit;i++)
1918                         {
1919                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1920                                 {
1921                                         if (p->vertexshader)
1922                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1923                                         if (p->pixelshader)
1924                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1925                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1926                                 }
1927                         }
1928                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1929                 }
1930 #endif
1931                 break;
1932         case RENDERPATH_D3D10:
1933                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1934                 break;
1935         case RENDERPATH_D3D11:
1936                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1937                 break;
1938         case RENDERPATH_GL20:
1939         case RENDERPATH_GLES2:
1940                 {
1941                         r_glsl_permutation_t *p;
1942                         r_glsl_permutation = NULL;
1943                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1944                         for (i = 0;i < limit;i++)
1945                         {
1946                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1947                                 {
1948                                         GL_Backend_FreeProgram(p->program);
1949                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1950                                 }
1951                         }
1952                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1953                 }
1954                 break;
1955         case RENDERPATH_GL11:
1956         case RENDERPATH_GL13:
1957         case RENDERPATH_GLES1:
1958                 break;
1959         case RENDERPATH_SOFT:
1960                 break;
1961         }
1962 }
1963
1964 static void R_GLSL_DumpShader_f(void)
1965 {
1966         int i, language, mode, dupe;
1967         char *text;
1968         shadermodeinfo_t *modeinfo;
1969         qfile_t *file;
1970
1971         for (language = 0;language < 2;language++)
1972         {
1973                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1974                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1975                 {
1976                         // don't dump the same file multiple times (most or all shaders come from the same file)
1977                         for (dupe = mode - 1;dupe >= 0;dupe--)
1978                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1979                                         break;
1980                         if (dupe >= 0)
1981                                 continue;
1982                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1983                         if (!text)
1984                                 continue;
1985                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1986                         if (file)
1987                         {
1988                                 FS_Print(file, "/* The engine may define the following macros:\n");
1989                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1990                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1991                                         FS_Print(file, modeinfo[i].pretext);
1992                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1993                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1994                                 FS_Print(file, "*/\n");
1995                                 FS_Print(file, text);
1996                                 FS_Close(file);
1997                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1998                         }
1999                         else
2000                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
2001                         Mem_Free(text);
2002                 }
2003         }
2004 }
2005
2006 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
2007 {
2008         unsigned int permutation = 0;
2009         if (r_trippy.integer && !notrippy)
2010                 permutation |= SHADERPERMUTATION_TRIPPY;
2011         permutation |= SHADERPERMUTATION_VIEWTINT;
2012         if (first)
2013                 permutation |= SHADERPERMUTATION_DIFFUSE;
2014         if (second)
2015                 permutation |= SHADERPERMUTATION_SPECULAR;
2016         if (texturemode == GL_MODULATE)
2017                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2018         else if (texturemode == GL_ADD)
2019                 permutation |= SHADERPERMUTATION_GLOW;
2020         else if (texturemode == GL_DECAL)
2021                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2022         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2023                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2024         if (suppresstexalpha)
2025                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2026         if (!second)
2027                 texturemode = GL_MODULATE;
2028         if (vid.allowalphatocoverage)
2029                 GL_AlphaToCoverage(false);
2030         switch (vid.renderpath)
2031         {
2032         case RENDERPATH_D3D9:
2033 #ifdef SUPPORTD3D
2034                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2035                 R_Mesh_TexBind(GL20TU_FIRST , first );
2036                 R_Mesh_TexBind(GL20TU_SECOND, second);
2037                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2038                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2039 #endif
2040                 break;
2041         case RENDERPATH_D3D10:
2042                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2043                 break;
2044         case RENDERPATH_D3D11:
2045                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2046                 break;
2047         case RENDERPATH_GL20:
2048         case RENDERPATH_GLES2:
2049                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2050                 if (r_glsl_permutation->tex_Texture_First >= 0)
2051                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2052                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2053                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2054                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2055                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2056                 break;
2057         case RENDERPATH_GL13:
2058         case RENDERPATH_GLES1:
2059                 R_Mesh_TexBind(0, first );
2060                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2061                 R_Mesh_TexMatrix(0, NULL);
2062                 R_Mesh_TexBind(1, second);
2063                 if (second)
2064                 {
2065                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2066                         R_Mesh_TexMatrix(1, NULL);
2067                 }
2068                 break;
2069         case RENDERPATH_GL11:
2070                 R_Mesh_TexBind(0, first );
2071                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2072                 R_Mesh_TexMatrix(0, NULL);
2073                 break;
2074         case RENDERPATH_SOFT:
2075                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2076                 R_Mesh_TexBind(GL20TU_FIRST , first );
2077                 R_Mesh_TexBind(GL20TU_SECOND, second);
2078                 break;
2079         }
2080 }
2081
2082 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2083 {
2084         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2085 }
2086
2087 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2088 {
2089         unsigned int permutation = 0;
2090         if (r_trippy.integer && !notrippy)
2091                 permutation |= SHADERPERMUTATION_TRIPPY;
2092         if (depthrgb)
2093                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2094         if (skeletal)
2095                 permutation |= SHADERPERMUTATION_SKELETAL;
2096
2097         if (vid.allowalphatocoverage)
2098                 GL_AlphaToCoverage(false);
2099         switch (vid.renderpath)
2100         {
2101         case RENDERPATH_D3D9:
2102 #ifdef SUPPORTD3D
2103                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2104 #endif
2105                 break;
2106         case RENDERPATH_D3D10:
2107                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2108                 break;
2109         case RENDERPATH_D3D11:
2110                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2111                 break;
2112         case RENDERPATH_GL20:
2113         case RENDERPATH_GLES2:
2114                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2115 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2116                 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2117 #endif
2118                 break;
2119         case RENDERPATH_GL13:
2120         case RENDERPATH_GLES1:
2121                 R_Mesh_TexBind(0, 0);
2122                 R_Mesh_TexBind(1, 0);
2123                 break;
2124         case RENDERPATH_GL11:
2125                 R_Mesh_TexBind(0, 0);
2126                 break;
2127         case RENDERPATH_SOFT:
2128                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2129                 break;
2130         }
2131 }
2132
2133 extern qboolean r_shadow_usingdeferredprepass;
2134 extern rtexture_t *r_shadow_attenuationgradienttexture;
2135 extern rtexture_t *r_shadow_attenuation2dtexture;
2136 extern rtexture_t *r_shadow_attenuation3dtexture;
2137 extern qboolean r_shadow_usingshadowmap2d;
2138 extern qboolean r_shadow_usingshadowmaportho;
2139 extern float r_shadow_shadowmap_texturescale[2];
2140 extern float r_shadow_shadowmap_parameters[4];
2141 extern qboolean r_shadow_shadowmapvsdct;
2142 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2143 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2144 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2145 extern matrix4x4_t r_shadow_shadowmapmatrix;
2146 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2147 extern int r_shadow_prepass_width;
2148 extern int r_shadow_prepass_height;
2149 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2150 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2151 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2152 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2153
2154 #define BLENDFUNC_ALLOWS_COLORMOD      1
2155 #define BLENDFUNC_ALLOWS_FOG           2
2156 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2157 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2158 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2159 static int R_BlendFuncFlags(int src, int dst)
2160 {
2161         int r = 0;
2162
2163         // a blendfunc allows colormod if:
2164         // a) it can never keep the destination pixel invariant, or
2165         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2166         // this is to prevent unintended side effects from colormod
2167
2168         // a blendfunc allows fog if:
2169         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2170         // this is to prevent unintended side effects from fog
2171
2172         // these checks are the output of fogeval.pl
2173
2174         r |= BLENDFUNC_ALLOWS_COLORMOD;
2175         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2176         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2177         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2178         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2179         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2180         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2181         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2182         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2183         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2184         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2185         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2186         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2187         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2188         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2189         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2190         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2191         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2192         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2193         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2194         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2195         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2196
2197         return r;
2198 }
2199
2200 void R_SetupShader_Surface(const vec3_t lightcolorbase, qboolean modellighting, float ambientscale, float diffusescale, float specularscale, rsurfacepass_t rsurfacepass, int texturenumsurfaces, const msurface_t **texturesurfacelist, void *surfacewaterplane, qboolean notrippy)
2201 {
2202         // select a permutation of the lighting shader appropriate to this
2203         // combination of texture, entity, light source, and fogging, only use the
2204         // minimum features necessary to avoid wasting rendering time in the
2205         // fragment shader on features that are not being used
2206         unsigned int permutation = 0;
2207         unsigned int mode = 0;
2208         int blendfuncflags;
2209         static float dummy_colormod[3] = {1, 1, 1};
2210         float *colormod = rsurface.colormod;
2211         float m16f[16];
2212         matrix4x4_t tempmatrix;
2213         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2214         if (r_trippy.integer && !notrippy)
2215                 permutation |= SHADERPERMUTATION_TRIPPY;
2216         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2217                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2218         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2219                 permutation |= SHADERPERMUTATION_OCCLUDE;
2220         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2221                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2222         if (rsurfacepass == RSURFPASS_BACKGROUND)
2223         {
2224                 // distorted background
2225                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2226                 {
2227                         mode = SHADERMODE_WATER;
2228                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2229                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2230                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2231                         {
2232                                 // this is the right thing to do for wateralpha
2233                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2234                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2235                         }
2236                         else
2237                         {
2238                                 // this is the right thing to do for entity alpha
2239                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2240                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2241                         }
2242                 }
2243                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2244                 {
2245                         mode = SHADERMODE_REFRACTION;
2246                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2247                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2248                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2249                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2250                 }
2251                 else
2252                 {
2253                         mode = SHADERMODE_GENERIC;
2254                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2255                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2256                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2257                 }
2258                 if (vid.allowalphatocoverage)
2259                         GL_AlphaToCoverage(false);
2260         }
2261         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2262         {
2263                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2264                 {
2265                         switch(rsurface.texture->offsetmapping)
2266                         {
2267                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2268                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2269                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2270                         case OFFSETMAPPING_OFF: break;
2271                         }
2272                 }
2273                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2274                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2275                 // normalmap (deferred prepass), may use alpha test on diffuse
2276                 mode = SHADERMODE_DEFERREDGEOMETRY;
2277                 GL_BlendFunc(GL_ONE, GL_ZERO);
2278                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2279                 if (vid.allowalphatocoverage)
2280                         GL_AlphaToCoverage(false);
2281         }
2282         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2283         {
2284                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2285                 {
2286                         switch(rsurface.texture->offsetmapping)
2287                         {
2288                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2289                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2290                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2291                         case OFFSETMAPPING_OFF: break;
2292                         }
2293                 }
2294                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2295                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2296                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2297                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2298                 // light source
2299                 mode = SHADERMODE_LIGHTSOURCE;
2300                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2301                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2302                 if (diffusescale > 0)
2303                         permutation |= SHADERPERMUTATION_DIFFUSE;
2304                 if (specularscale > 0)
2305                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2306                 if (r_refdef.fogenabled)
2307                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2308                 if (rsurface.texture->colormapping)
2309                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2310                 if (r_shadow_usingshadowmap2d)
2311                 {
2312                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2313                         if(r_shadow_shadowmapvsdct)
2314                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2315
2316                         if (r_shadow_shadowmap2ddepthbuffer)
2317                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2318                 }
2319                 if (rsurface.texture->reflectmasktexture)
2320                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2321                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2322                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2323                 if (vid.allowalphatocoverage)
2324                         GL_AlphaToCoverage(false);
2325         }
2326         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2327         {
2328                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2329                 {
2330                         switch(rsurface.texture->offsetmapping)
2331                         {
2332                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2333                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2334                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2335                         case OFFSETMAPPING_OFF: break;
2336                         }
2337                 }
2338                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2339                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2340                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2341                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2342                 // unshaded geometry (fullbright or ambient model lighting)
2343                 mode = SHADERMODE_FLATCOLOR;
2344                 ambientscale = diffusescale = specularscale = 0;
2345                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2346                         permutation |= SHADERPERMUTATION_GLOW;
2347                 if (r_refdef.fogenabled)
2348                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2349                 if (rsurface.texture->colormapping)
2350                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2351                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2352                 {
2353                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2354                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2355
2356                         if (r_shadow_shadowmap2ddepthbuffer)
2357                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2358                 }
2359                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2360                         permutation |= SHADERPERMUTATION_REFLECTION;
2361                 if (rsurface.texture->reflectmasktexture)
2362                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2363                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2364                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2365                 // when using alphatocoverage, we don't need alphakill
2366                 if (vid.allowalphatocoverage)
2367                 {
2368                         if (r_transparent_alphatocoverage.integer)
2369                         {
2370                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2371                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2372                         }
2373                         else
2374                                 GL_AlphaToCoverage(false);
2375                 }
2376         }
2377         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2378         {
2379                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2380                 {
2381                         switch(rsurface.texture->offsetmapping)
2382                         {
2383                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2384                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2385                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2386                         case OFFSETMAPPING_OFF: break;
2387                         }
2388                 }
2389                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2390                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2391                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2392                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2393                 // directional model lighting
2394                 mode = SHADERMODE_LIGHTDIRECTION;
2395                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2396                         permutation |= SHADERPERMUTATION_GLOW;
2397                 permutation |= SHADERPERMUTATION_DIFFUSE;
2398                 if (specularscale > 0)
2399                         permutation |= SHADERPERMUTATION_SPECULAR;
2400                 if (r_refdef.fogenabled)
2401                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2402                 if (rsurface.texture->colormapping)
2403                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2404                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2405                 {
2406                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2407                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2408
2409                         if (r_shadow_shadowmap2ddepthbuffer)
2410                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2411                 }
2412                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2413                         permutation |= SHADERPERMUTATION_REFLECTION;
2414                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2415                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2416                 if (rsurface.texture->reflectmasktexture)
2417                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2418                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2419                 {
2420                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2421                         if (r_shadow_bouncegrid_state.directional)
2422                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2423                 }
2424                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2425                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2426                 // when using alphatocoverage, we don't need alphakill
2427                 if (vid.allowalphatocoverage)
2428                 {
2429                         if (r_transparent_alphatocoverage.integer)
2430                         {
2431                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2432                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2433                         }
2434                         else
2435                                 GL_AlphaToCoverage(false);
2436                 }
2437         }
2438         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2439         {
2440                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2441                 {
2442                         switch(rsurface.texture->offsetmapping)
2443                         {
2444                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2445                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2446                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2447                         case OFFSETMAPPING_OFF: break;
2448                         }
2449                 }
2450                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2451                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2452                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2453                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2454                 // ambient model lighting
2455                 mode = SHADERMODE_LIGHTDIRECTION;
2456                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2457                         permutation |= SHADERPERMUTATION_GLOW;
2458                 if (r_refdef.fogenabled)
2459                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2460                 if (rsurface.texture->colormapping)
2461                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2462                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2463                 {
2464                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2465                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2466
2467                         if (r_shadow_shadowmap2ddepthbuffer)
2468                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2469                 }
2470                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2471                         permutation |= SHADERPERMUTATION_REFLECTION;
2472                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2473                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2474                 if (rsurface.texture->reflectmasktexture)
2475                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2476                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2477                 {
2478                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2479                         if (r_shadow_bouncegrid_state.directional)
2480                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2481                 }
2482                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2483                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2484                 // when using alphatocoverage, we don't need alphakill
2485                 if (vid.allowalphatocoverage)
2486                 {
2487                         if (r_transparent_alphatocoverage.integer)
2488                         {
2489                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2490                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2491                         }
2492                         else
2493                                 GL_AlphaToCoverage(false);
2494                 }
2495         }
2496         else
2497         {
2498                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2499                 {
2500                         switch(rsurface.texture->offsetmapping)
2501                         {
2502                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2503                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2504                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2505                         case OFFSETMAPPING_OFF: break;
2506                         }
2507                 }
2508                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2509                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2510                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2511                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2512                 // lightmapped wall
2513                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2514                         permutation |= SHADERPERMUTATION_GLOW;
2515                 if (r_refdef.fogenabled)
2516                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2517                 if (rsurface.texture->colormapping)
2518                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2519                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2520                 {
2521                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2522                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2523
2524                         if (r_shadow_shadowmap2ddepthbuffer)
2525                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2526                 }
2527                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2528                         permutation |= SHADERPERMUTATION_REFLECTION;
2529                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2530                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2531                 if (rsurface.texture->reflectmasktexture)
2532                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2533                 if (FAKELIGHT_ENABLED)
2534                 {
2535                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2536                         mode = SHADERMODE_FAKELIGHT;
2537                         permutation |= SHADERPERMUTATION_DIFFUSE;
2538                         if (specularscale > 0)
2539                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2540                 }
2541                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2542                 {
2543                         // deluxemapping (light direction texture)
2544                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2545                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2546                         else
2547                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2548                         permutation |= SHADERPERMUTATION_DIFFUSE;
2549                         if (specularscale > 0)
2550                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2551                 }
2552                 else if (r_glsl_deluxemapping.integer >= 2)
2553                 {
2554                         // fake deluxemapping (uniform light direction in tangentspace)
2555                         if (rsurface.uselightmaptexture)
2556                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2557                         else
2558                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2559                         permutation |= SHADERPERMUTATION_DIFFUSE;
2560                         if (specularscale > 0)
2561                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2562                 }
2563                 else if (rsurface.uselightmaptexture)
2564                 {
2565                         // ordinary lightmapping (q1bsp, q3bsp)
2566                         mode = SHADERMODE_LIGHTMAP;
2567                 }
2568                 else
2569                 {
2570                         // ordinary vertex coloring (q3bsp)
2571                         mode = SHADERMODE_VERTEXCOLOR;
2572                 }
2573                 if (r_shadow_bouncegrid_state.texture && cl.csqc_vidvars.drawworld)
2574                 {
2575                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2576                         if (r_shadow_bouncegrid_state.directional)
2577                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2578                 }
2579                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2580                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2581                 // when using alphatocoverage, we don't need alphakill
2582                 if (vid.allowalphatocoverage)
2583                 {
2584                         if (r_transparent_alphatocoverage.integer)
2585                         {
2586                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2587                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2588                         }
2589                         else
2590                                 GL_AlphaToCoverage(false);
2591                 }
2592         }
2593         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2594                 colormod = dummy_colormod;
2595         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2596                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2597         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2598                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2599         switch(vid.renderpath)
2600         {
2601         case RENDERPATH_D3D9:
2602 #ifdef SUPPORTD3D
2603                 RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2604                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2605                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2606                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2607                 if (mode == SHADERMODE_LIGHTSOURCE)
2608                 {
2609                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2610                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2611                 }
2612                 else
2613                 {
2614                         if (mode == SHADERMODE_LIGHTDIRECTION)
2615                         {
2616                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2617                         }
2618                 }
2619                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2620                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2621                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2622                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2623                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2624
2625                 if (mode == SHADERMODE_LIGHTSOURCE)
2626                 {
2627                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2628                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2629                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2630                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2631                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2632
2633                         // additive passes are only darkened by fog, not tinted
2634                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2635                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2636                 }
2637                 else
2638                 {
2639                         if (mode == SHADERMODE_FLATCOLOR)
2640                         {
2641                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2642                         }
2643                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2644                         {
2645                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity) * colormod[2]);
2646                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2647                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2648                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2649                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2650                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2651                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2652                         }
2653                         else
2654                         {
2655                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2656                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2657                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2658                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2659                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2660                         }
2661                         // additive passes are only darkened by fog, not tinted
2662                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2663                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2664                         else
2665                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2666                         hlslPSSetParameter4f(D3DPSREGISTER_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2667                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2668                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2669                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2670                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2671                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2672                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2673                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2674                         if (mode == SHADERMODE_WATER)
2675                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2676                 }
2677                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2678                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2679                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2680                 hlslPSSetParameter1f(D3DPSREGISTER_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2681                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2682                 if (rsurface.texture->pantstexture)
2683                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2684                 else
2685                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2686                 if (rsurface.texture->shirttexture)
2687                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2688                 else
2689                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2690                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2691                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2692                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2693                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2694                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2695                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2696                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2697                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2698                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2699                         );
2700                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2701                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2702                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2703                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2704
2705                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2706                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2707                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2708                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2709                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2710                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2711                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2712                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2713                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2714                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2715                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2716                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2717                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2718                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2719                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2720                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2721                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2722                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2723                 {
2724                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2725                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2726                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2727                 }
2728                 else
2729                 {
2730                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2731                 }
2732 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2733                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2734                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2735                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2736                 {
2737                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2738                         if (rsurface.rtlight)
2739                         {
2740                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2741                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2742                         }
2743                 }
2744 #endif
2745                 break;
2746         case RENDERPATH_D3D10:
2747                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2748                 break;
2749         case RENDERPATH_D3D11:
2750                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2751                 break;
2752         case RENDERPATH_GL20:
2753         case RENDERPATH_GLES2:
2754                 if (!vid.useinterleavedarrays)
2755                 {
2756                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2757                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2758                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2759                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2760                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2761                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2762                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2763                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2764                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2765                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2766                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2767                 }
2768                 else
2769                 {
2770                         RSurf_PrepareVerticesForBatch(BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_VERTEXMESH_VERTEXCOLOR : 0) | BATCHNEED_VERTEXMESH_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_VERTEXMESH_LIGHTMAP : 0) | (rsurface.entityskeletaltransform3x4 ? BATCHNEED_VERTEXMESH_SKELETAL : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2771                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2772                 }
2773                 // this has to be after RSurf_PrepareVerticesForBatch
2774                 if (rsurface.batchskeletaltransform3x4buffer)
2775                         permutation |= SHADERPERMUTATION_SKELETAL;
2776                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2777 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2778                 if (r_glsl_permutation->ubiloc_Skeletal_Transform12_UniformBlock >= 0 && rsurface.batchskeletaltransform3x4buffer) qglBindBufferRange(GL_UNIFORM_BUFFER, r_glsl_permutation->ubibind_Skeletal_Transform12_UniformBlock, rsurface.batchskeletaltransform3x4buffer->bufferobject, rsurface.batchskeletaltransform3x4offset, rsurface.batchskeletaltransform3x4size);
2779 #endif
2780                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2781                 if (mode == SHADERMODE_LIGHTSOURCE)
2782                 {
2783                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2784                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2785                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2786                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2787                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2788                         if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2789         
2790                         // additive passes are only darkened by fog, not tinted
2791                         if (r_glsl_permutation->loc_FogColor >= 0)
2792                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2793                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2794                 }
2795                 else
2796                 {
2797                         if (mode == SHADERMODE_FLATCOLOR)
2798                         {
2799                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2800                         }
2801                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2802                         {
2803                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2804                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2805                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2806                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2807                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2808                                 if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2809                                 if (r_glsl_permutation->loc_LightDir >= 0) qglUniform3f(r_glsl_permutation->loc_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2810                         }
2811                         else
2812                         {
2813                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2814                                 if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2815                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2816                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2817                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2818                         }
2819                         // additive passes are only darkened by fog, not tinted
2820                         if (r_glsl_permutation->loc_FogColor >= 0)
2821                         {
2822                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2823                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2824                                 else
2825                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2826                         }
2827                         if (r_glsl_permutation->loc_DistortScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2828                         if (r_glsl_permutation->loc_ScreenScaleRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2829                         if (r_glsl_permutation->loc_ScreenCenterRefractReflect >= 0) qglUniform4f(r_glsl_permutation->loc_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2830                         if (r_glsl_permutation->loc_RefractColor >= 0) qglUniform4f(r_glsl_permutation->loc_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2831                         if (r_glsl_permutation->loc_ReflectColor >= 0) qglUniform4f(r_glsl_permutation->loc_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2832                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2833                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2834                         if (r_glsl_permutation->loc_SpecularPower >= 0) qglUniform1f(r_glsl_permutation->loc_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2835                         if (r_glsl_permutation->loc_NormalmapScrollBlend >= 0) qglUniform2f(r_glsl_permutation->loc_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2836                 }
2837                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2838                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2839                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2840                 if (r_glsl_permutation->loc_ShadowMap_TextureScale >= 0) qglUniform2f(r_glsl_permutation->loc_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2841                 if (r_glsl_permutation->loc_ShadowMap_Parameters >= 0) qglUniform4f(r_glsl_permutation->loc_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2842
2843                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2844                 if (r_glsl_permutation->loc_Alpha >= 0) qglUniform1f(r_glsl_permutation->loc_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2845                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2846                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2847                 {
2848                         if (rsurface.texture->pantstexture)
2849                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2850                         else
2851                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2852                 }
2853                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2854                 {
2855                         if (rsurface.texture->shirttexture)
2856                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2857                         else
2858                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2859                 }
2860                 if (r_glsl_permutation->loc_FogPlane >= 0) qglUniform4f(r_glsl_permutation->loc_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2861                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2862                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2863                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2864                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2865                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2866                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2867                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2868                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2869                         );
2870                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2871                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2872                 if (r_glsl_permutation->loc_ScreenToDepth >= 0) qglUniform2f(r_glsl_permutation->loc_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2873                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2874                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegrid_state.matrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2875                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegrid_state.intensity*r_refdef.view.colorscale);
2876
2877                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2878                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2879                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2880                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2881                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2882                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2883                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2884                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2885                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2886                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2887                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2888                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2889                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2890                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2891                 if (r_glsl_permutation->tex_Texture_ReflectCube     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectCube      , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2892                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2893                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2894                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2895                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2896                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2897                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2898                 {
2899                         if (r_glsl_permutation->tex_Texture_Refraction  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Refraction        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2900                         if (r_glsl_permutation->tex_Texture_First       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2901                         if (r_glsl_permutation->tex_Texture_Reflection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2902                 }
2903                 else
2904                 {
2905                         if (r_glsl_permutation->tex_Texture_Reflection >= 0 && waterplane) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Reflection        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2906                 }
2907                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2908                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2909                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2910                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2911                 {
2912                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2913                         if (rsurface.rtlight)
2914                         {
2915                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2916                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2917                         }
2918                 }
2919                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegrid_state.texture);
2920                 CHECKGLERROR
2921                 break;
2922         case RENDERPATH_GL11:
2923         case RENDERPATH_GL13:
2924         case RENDERPATH_GLES1:
2925                 break;
2926         case RENDERPATH_SOFT:
2927                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | (rsurface.modellightmapcolor4f ? BATCHNEED_ARRAY_VERTEXCOLOR : 0) | BATCHNEED_ARRAY_TEXCOORD | (rsurface.uselightmaptexture ? BATCHNEED_ARRAY_LIGHTMAP : 0) | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
2928                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2929                 R_SetupShader_SetPermutationSoft(mode, permutation);
2930                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2931                 if (mode == SHADERMODE_LIGHTSOURCE)
2932                 {
2933                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2934                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2935                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2936                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2937                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2938                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2939         
2940                         // additive passes are only darkened by fog, not tinted
2941                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2942                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2943                 }
2944                 else
2945                 {
2946                         if (mode == SHADERMODE_FLATCOLOR)
2947                         {
2948                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2949                         }
2950                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2951                         {
2952                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, (r_refdef.scene.ambient + rsurface.modellight_ambient[0] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[0], (r_refdef.scene.ambient + rsurface.modellight_ambient[1] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[1], (r_refdef.scene.ambient + rsurface.modellight_ambient[2] * r_refdef.lightmapintensity * r_refdef.scene.rtlightstylevalue[0]) * colormod[2]);
2953                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2954                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2955                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2956                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2957                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, rsurface.modellight_diffuse[0] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[1] * r_refdef.scene.rtlightstylevalue[0], rsurface.modellight_diffuse[2] * r_refdef.scene.rtlightstylevalue[0]);
2958                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2959                         }
2960                         else
2961                         {
2962                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2963                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2964                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2965                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2966                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2967                         }
2968                         // additive passes are only darkened by fog, not tinted
2969                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2970                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2971                         else
2972                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2973                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_DistortScaleRefractReflect, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_refractdistort.value * rsurface.texture->refractfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor, r_water_reflectdistort.value * rsurface.texture->reflectfactor);
2974                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2975                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2976                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2977                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2978                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2979                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2980                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2981                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2982                 }
2983                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2984                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2985                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2986                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2987                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2988
2989                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2990                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Alpha, rsurface.texture->lightmapcolor[3] * ((rsurface.texture->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay) ? rsurface.texture->r_water_wateralpha : 1));
2991                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2992                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2993                 {
2994                         if (rsurface.texture->pantstexture)
2995                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2996                         else
2997                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2998                 }
2999                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
3000                 {
3001                         if (rsurface.texture->shirttexture)
3002                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
3003                         else
3004                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
3005                 }
3006                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
3007                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
3008                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
3009                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
3010                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
3011                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3012                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3013                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3014                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3015                         );
3016                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3017                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3018                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3019                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3020
3021                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3022                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3023                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3024                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3025                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3026                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3027                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3028                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3029                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3030                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3031                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3032                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3033                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3034                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3035                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3036                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3037                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3038                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3039                 {
3040                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3041                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3042                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3043                 }
3044                 else
3045                 {
3046                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3047                 }
3048 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3049                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3050                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3051                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3052                 {
3053                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3054                         if (rsurface.rtlight)
3055                         {
3056                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3057                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3058                         }
3059                 }
3060                 break;
3061         }
3062 }
3063
3064 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3065 {
3066         // select a permutation of the lighting shader appropriate to this
3067         // combination of texture, entity, light source, and fogging, only use the
3068         // minimum features necessary to avoid wasting rendering time in the
3069         // fragment shader on features that are not being used
3070         unsigned int permutation = 0;
3071         unsigned int mode = 0;
3072         const float *lightcolorbase = rtlight->currentcolor;
3073         float ambientscale = rtlight->ambientscale;
3074         float diffusescale = rtlight->diffusescale;
3075         float specularscale = rtlight->specularscale;
3076         // this is the location of the light in view space
3077         vec3_t viewlightorigin;
3078         // this transforms from view space (camera) to light space (cubemap)
3079         matrix4x4_t viewtolight;
3080         matrix4x4_t lighttoview;
3081         float viewtolight16f[16];
3082         // light source
3083         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3084         if (rtlight->currentcubemap != r_texture_whitecube)
3085                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3086         if (diffusescale > 0)
3087                 permutation |= SHADERPERMUTATION_DIFFUSE;
3088         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3089                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3090         if (r_shadow_usingshadowmap2d)
3091         {
3092                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3093                 if (r_shadow_shadowmapvsdct)
3094                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3095
3096                 if (r_shadow_shadowmap2ddepthbuffer)
3097                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3098         }
3099         if (vid.allowalphatocoverage)
3100                 GL_AlphaToCoverage(false);
3101         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3102         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3103         Matrix4x4_Invert_Full(&viewtolight, &lighttoview);
3104         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3105         switch(vid.renderpath)
3106         {
3107         case RENDERPATH_D3D9:
3108 #ifdef SUPPORTD3D
3109                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3110                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3111                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3112                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3113                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3114                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3115                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3116                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3117                 hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3118                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3119                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3120
3121                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3122                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3123                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3124                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3125                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3126 #endif
3127                 break;
3128         case RENDERPATH_D3D10:
3129                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3130                 break;
3131         case RENDERPATH_D3D11:
3132                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3133                 break;
3134         case RENDERPATH_GL20:
3135         case RENDERPATH_GLES2:
3136                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3137                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3138                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3139                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3140                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3141                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3142                 if (r_glsl_permutation->loc_ShadowMap_TextureScale    >= 0) qglUniform2f(       r_glsl_permutation->loc_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3143                 if (r_glsl_permutation->loc_ShadowMap_Parameters      >= 0) qglUniform4f(       r_glsl_permutation->loc_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3144                 if (r_glsl_permutation->loc_SpecularPower             >= 0) qglUniform1f(       r_glsl_permutation->loc_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3145                 if (r_glsl_permutation->loc_ScreenToDepth             >= 0) qglUniform2f(       r_glsl_permutation->loc_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3146                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3147
3148                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3149                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3150                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3151                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3152                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3153                 break;
3154         case RENDERPATH_GL11:
3155         case RENDERPATH_GL13:
3156         case RENDERPATH_GLES1:
3157                 break;
3158         case RENDERPATH_SOFT:
3159                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3160                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3161                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3162                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3163                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3164                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3165                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3166                 DPSOFTRAST_Uniform4f(       DPSOFTRAST_UNIFORM_ShadowMap_Parameters     , r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3167                 DPSOFTRAST_Uniform1f(       DPSOFTRAST_UNIFORM_SpecularPower            , (r_shadow_gloss.integer == 2 ? r_shadow_gloss2exponent.value : r_shadow_glossexponent.value) * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
3168                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3169                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3170
3171                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3172                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3173                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3174                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3175                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3176                 break;
3177         }
3178 }
3179
3180 #define SKINFRAME_HASH 1024
3181
3182 typedef struct
3183 {
3184         unsigned int loadsequence; // incremented each level change
3185         memexpandablearray_t array;
3186         skinframe_t *hash[SKINFRAME_HASH];
3187 }
3188 r_skinframe_t;
3189 r_skinframe_t r_skinframe;
3190
3191 void R_SkinFrame_PrepareForPurge(void)
3192 {
3193         r_skinframe.loadsequence++;
3194         // wrap it without hitting zero
3195         if (r_skinframe.loadsequence >= 200)
3196                 r_skinframe.loadsequence = 1;
3197 }
3198
3199 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3200 {
3201         if (!skinframe)
3202                 return;
3203         // mark the skinframe as used for the purging code
3204         skinframe->loadsequence = r_skinframe.loadsequence;
3205 }
3206
3207 void R_SkinFrame_Purge(void)
3208 {
3209         int i;
3210         skinframe_t *s;
3211         for (i = 0;i < SKINFRAME_HASH;i++)
3212         {
3213                 for (s = r_skinframe.hash[i];s;s = s->next)
3214                 {
3215                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3216                         {
3217                                 if (s->merged == s->base)
3218                                         s->merged = NULL;
3219                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3220                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3221                                 R_PurgeTexture(s->merged);s->merged = NULL;
3222                                 R_PurgeTexture(s->base  );s->base   = NULL;
3223                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3224                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3225                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3226                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3227                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3228                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3229                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3230                                 s->loadsequence = 0;
3231                         }
3232                 }
3233         }
3234 }
3235
3236 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3237         skinframe_t *item;
3238         char basename[MAX_QPATH];
3239
3240         Image_StripImageExtension(name, basename, sizeof(basename));
3241
3242         if( last == NULL ) {
3243                 int hashindex;
3244                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3245                 item = r_skinframe.hash[hashindex];
3246         } else {
3247                 item = last->next;
3248         }
3249
3250         // linearly search through the hash bucket
3251         for( ; item ; item = item->next ) {
3252                 if( !strcmp( item->basename, basename ) ) {
3253                         return item;
3254                 }
3255         }
3256         return NULL;
3257 }
3258
3259 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3260 {
3261         skinframe_t *item;
3262         int hashindex;
3263         char basename[MAX_QPATH];
3264
3265         Image_StripImageExtension(name, basename, sizeof(basename));
3266
3267         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3268         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3269                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3270                         break;
3271
3272         if (!item) {
3273                 rtexture_t *dyntexture;
3274                 // check whether its a dynamic texture
3275                 dyntexture = CL_GetDynTexture( basename );
3276                 if (!add && !dyntexture)
3277                         return NULL;
3278                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3279                 memset(item, 0, sizeof(*item));
3280                 strlcpy(item->basename, basename, sizeof(item->basename));
3281                 item->base = dyntexture; // either NULL or dyntexture handle
3282                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3283                 item->comparewidth = comparewidth;
3284                 item->compareheight = compareheight;
3285                 item->comparecrc = comparecrc;
3286                 item->next = r_skinframe.hash[hashindex];
3287                 r_skinframe.hash[hashindex] = item;
3288         }
3289         else if (textureflags & TEXF_FORCE_RELOAD)
3290         {
3291                 rtexture_t *dyntexture;
3292                 // check whether its a dynamic texture
3293                 dyntexture = CL_GetDynTexture( basename );
3294                 if (!add && !dyntexture)
3295                         return NULL;
3296                 if (item->merged == item->base)
3297                         item->merged = NULL;
3298                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3299                 R_PurgeTexture(item->stain );item->stain  = NULL;
3300                 R_PurgeTexture(item->merged);item->merged = NULL;
3301                 R_PurgeTexture(item->base  );item->base   = NULL;
3302                 R_PurgeTexture(item->pants );item->pants  = NULL;
3303                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3304                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3305                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3306                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3307                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3308         R_PurgeTexture(item->reflect);item->reflect = NULL;
3309                 item->loadsequence = 0;
3310         }
3311         else if( item->base == NULL )
3312         {
3313                 rtexture_t *dyntexture;
3314                 // check whether its a dynamic texture
3315                 // this only needs to be done because Purge doesnt delete skinframes - only sets the texture pointers to NULL and we need to restore it before returing.. [11/29/2007 Black]
3316                 dyntexture = CL_GetDynTexture( basename );
3317                 item->base = dyntexture; // either NULL or dyntexture handle
3318         }
3319
3320         R_SkinFrame_MarkUsed(item);
3321         return item;
3322 }
3323
3324 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3325         { \
3326                 unsigned long long avgcolor[5], wsum; \
3327                 int pix, comp, w; \
3328                 avgcolor[0] = 0; \
3329                 avgcolor[1] = 0; \
3330                 avgcolor[2] = 0; \
3331                 avgcolor[3] = 0; \
3332                 avgcolor[4] = 0; \
3333                 wsum = 0; \
3334                 for(pix = 0; pix < cnt; ++pix) \
3335                 { \
3336                         w = 0; \
3337                         for(comp = 0; comp < 3; ++comp) \
3338                                 w += getpixel; \
3339                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3340                         { \
3341                                 ++wsum; \
3342                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3343                                 w = getpixel; \
3344                                 for(comp = 0; comp < 3; ++comp) \
3345                                         avgcolor[comp] += getpixel * w; \
3346                                 avgcolor[3] += w; \
3347                         } \
3348                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3349                         avgcolor[4] += getpixel; \
3350                 } \
3351                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3352                         avgcolor[3] = 1; \
3353                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3354                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3355                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3356                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3357         }
3358
3359 extern cvar_t gl_picmip;
3360 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3361 {
3362         int j;
3363         unsigned char *pixels;
3364         unsigned char *bumppixels;
3365         unsigned char *basepixels = NULL;
3366         int basepixels_width = 0;
3367         int basepixels_height = 0;
3368         skinframe_t *skinframe;
3369         rtexture_t *ddsbase = NULL;
3370         qboolean ddshasalpha = false;
3371         float ddsavgcolor[4];
3372         char basename[MAX_QPATH];
3373         int miplevel = R_PicmipForFlags(textureflags);
3374         int savemiplevel = miplevel;
3375         int mymiplevel;
3376         char vabuf[1024];
3377
3378         if (cls.state == ca_dedicated)
3379                 return NULL;
3380
3381         // return an existing skinframe if already loaded
3382         // if loading of the first image fails, don't make a new skinframe as it
3383         // would cause all future lookups of this to be missing
3384         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3385         if (skinframe && skinframe->base)
3386                 return skinframe;
3387
3388         Image_StripImageExtension(name, basename, sizeof(basename));
3389
3390         // check for DDS texture file first
3391         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3392         {
3393                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3394                 if (basepixels == NULL)
3395                         return NULL;
3396         }
3397
3398         // FIXME handle miplevel
3399
3400         if (developer_loading.integer)
3401                 Con_Printf("loading skin \"%s\"\n", name);
3402
3403         // we've got some pixels to store, so really allocate this new texture now
3404         if (!skinframe)
3405                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3406         textureflags &= ~TEXF_FORCE_RELOAD;
3407         skinframe->stain = NULL;
3408         skinframe->merged = NULL;
3409         skinframe->base = NULL;
3410         skinframe->pants = NULL;
3411         skinframe->shirt = NULL;
3412         skinframe->nmap = NULL;
3413         skinframe->gloss = NULL;
3414         skinframe->glow = NULL;
3415         skinframe->fog = NULL;
3416         skinframe->reflect = NULL;
3417         skinframe->hasalpha = false;
3418         // we could store the q2animname here too
3419
3420         if (ddsbase)
3421         {
3422                 skinframe->base = ddsbase;
3423                 skinframe->hasalpha = ddshasalpha;
3424                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3425                 if (r_loadfog && skinframe->hasalpha)
3426                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel, true);
3427                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3428         }
3429         else
3430         {
3431                 basepixels_width = image_width;
3432                 basepixels_height = image_height;
3433                 skinframe->base = R_LoadTexture2D (r_main_texturepool, skinframe->basename, basepixels_width, basepixels_height, basepixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3434                 if (textureflags & TEXF_ALPHA)
3435                 {
3436                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3437                         {
3438                                 if (basepixels[j] < 255)
3439                                 {
3440                                         skinframe->hasalpha = true;
3441                                         break;
3442                                 }
3443                         }
3444                         if (r_loadfog && skinframe->hasalpha)
3445                         {
3446                                 // has transparent pixels
3447                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3448                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3449                                 {
3450                                         pixels[j+0] = 255;
3451                                         pixels[j+1] = 255;
3452                                         pixels[j+2] = 255;
3453                                         pixels[j+3] = basepixels[j+3];
3454                                 }
3455                                 skinframe->fog = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_mask", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), miplevel, NULL);
3456                                 Mem_Free(pixels);
3457                         }
3458                 }
3459                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3460 #ifndef USE_GLES2
3461                 //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3462                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3463                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3464                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3465                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3466 #endif
3467         }
3468
3469         if (r_loaddds)
3470         {
3471                 mymiplevel = savemiplevel;
3472                 if (r_loadnormalmap)
3473                         skinframe->nmap = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), false, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), NULL, NULL, mymiplevel, true);
3474                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3475                 if (r_loadgloss)
3476                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3477                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3478                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3479                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3480         }
3481
3482         // _norm is the name used by tenebrae and has been adopted as standard
3483         if (r_loadnormalmap && skinframe->nmap == NULL)
3484         {
3485                 mymiplevel = savemiplevel;
3486                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3487                 {
3488                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3489                         Mem_Free(pixels);
3490                         pixels = NULL;
3491                 }
3492                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3493                 {
3494                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3495                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3496                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3497                         Mem_Free(pixels);
3498                         Mem_Free(bumppixels);
3499                 }
3500                 else if (r_shadow_bumpscale_basetexture.value > 0)
3501                 {
3502                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3503                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3504                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), basepixels_width, basepixels_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3505                         Mem_Free(pixels);
3506                 }
3507 #ifndef USE_GLES2
3508                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3509                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3510 #endif
3511         }
3512
3513         // _luma is supported only for tenebrae compatibility
3514         // _glow is the preferred name
3515         mymiplevel = savemiplevel;
3516         if (skinframe->glow == NULL && ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_glow",  skinframe->basename), false, false, false, &mymiplevel)) || (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_luma", skinframe->basename), false, false, false, &mymiplevel))))
3517         {
3518                 skinframe->glow = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_glow.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3519 #ifndef USE_GLES2
3520                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3521                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3522 #endif
3523                 Mem_Free(pixels);pixels = NULL;
3524         }
3525
3526         mymiplevel = savemiplevel;
3527         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3528         {
3529                 skinframe->gloss = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (gl_texturecompression_gloss.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3530 #ifndef USE_GLES2
3531                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3532                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3533 #endif
3534                 Mem_Free(pixels);
3535                 pixels = NULL;
3536         }
3537
3538         mymiplevel = savemiplevel;
3539         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3540         {
3541                 skinframe->pants = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3542 #ifndef USE_GLES2
3543                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3544                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3545 #endif
3546                 Mem_Free(pixels);
3547                 pixels = NULL;
3548         }
3549
3550         mymiplevel = savemiplevel;
3551         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3552         {
3553                 skinframe->shirt = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_color.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3554 #ifndef USE_GLES2
3555                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3556                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3557 #endif
3558                 Mem_Free(pixels);
3559                 pixels = NULL;
3560         }
3561
3562         mymiplevel = savemiplevel;
3563         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3564         {
3565                 skinframe->reflect = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), image_width, image_height, pixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags & (gl_texturecompression_reflectmask.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3566 #ifndef USE_GLES2
3567                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3568                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3569 #endif
3570                 Mem_Free(pixels);
3571                 pixels = NULL;
3572         }
3573
3574         if (basepixels)
3575                 Mem_Free(basepixels);
3576
3577         return skinframe;
3578 }
3579
3580 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3581 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3582 {
3583         int i;
3584         unsigned char *temp1, *temp2;
3585         skinframe_t *skinframe;
3586         char vabuf[1024];
3587
3588         if (cls.state == ca_dedicated)
3589                 return NULL;
3590
3591         // if already loaded just return it, otherwise make a new skinframe
3592         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3593         if (skinframe->base)
3594                 return skinframe;
3595         textureflags &= ~TEXF_FORCE_RELOAD;
3596
3597         skinframe->stain = NULL;
3598         skinframe->merged = NULL;
3599         skinframe->base = NULL;
3600         skinframe->pants = NULL;
3601         skinframe->shirt = NULL;
3602         skinframe->nmap = NULL;
3603         skinframe->gloss = NULL;
3604         skinframe->glow = NULL;
3605         skinframe->fog = NULL;
3606         skinframe->reflect = NULL;
3607         skinframe->hasalpha = false;
3608
3609         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3610         if (!skindata)
3611                 return NULL;
3612
3613         if (developer_loading.integer)
3614                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3615
3616         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3617         {
3618                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3619                 temp2 = temp1 + width * height * 4;
3620                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3621                 skinframe->nmap = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), width, height, temp2, TEXTYPE_BGRA, (textureflags | TEXF_ALPHA) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP), -1, NULL);
3622                 Mem_Free(temp1);
3623         }
3624         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3625         if (textureflags & TEXF_ALPHA)
3626         {
3627                 for (i = 3;i < width * height * 4;i += 4)
3628                 {
3629                         if (skindata[i] < 255)
3630                         {
3631                                 skinframe->hasalpha = true;
3632                                 break;
3633                         }
3634                 }
3635                 if (r_loadfog && skinframe->hasalpha)
3636                 {
3637                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3638                         memcpy(fogpixels, skindata, width * height * 4);
3639                         for (i = 0;i < width * height * 4;i += 4)
3640                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3641                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3642                         Mem_Free(fogpixels);
3643                 }
3644         }
3645
3646         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3647         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3648
3649         return skinframe;
3650 }
3651
3652 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3653 {
3654         int i;
3655         int featuresmask;
3656         skinframe_t *skinframe;
3657
3658         if (cls.state == ca_dedicated)
3659                 return NULL;
3660
3661         // if already loaded just return it, otherwise make a new skinframe
3662         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3663         if (skinframe->base)
3664                 return skinframe;
3665         //textureflags &= ~TEXF_FORCE_RELOAD;
3666
3667         skinframe->stain = NULL;
3668         skinframe->merged = NULL;
3669         skinframe->base = NULL;
3670         skinframe->pants = NULL;
3671         skinframe->shirt = NULL;
3672         skinframe->nmap = NULL;
3673         skinframe->gloss = NULL;
3674         skinframe->glow = NULL;
3675         skinframe->fog = NULL;
3676         skinframe->reflect = NULL;
3677         skinframe->hasalpha = false;
3678
3679         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3680         if (!skindata)
3681                 return NULL;
3682
3683         if (developer_loading.integer)
3684                 Con_Printf("loading quake skin \"%s\"\n", name);
3685
3686         // we actually don't upload anything until the first use, because mdl skins frequently go unused, and are almost never used in both modes (colormapped and non-colormapped)
3687         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3688         memcpy(skinframe->qpixels, skindata, width*height);
3689         skinframe->qwidth = width;
3690         skinframe->qheight = height;
3691
3692         featuresmask = 0;
3693         for (i = 0;i < width * height;i++)
3694                 featuresmask |= palette_featureflags[skindata[i]];
3695
3696         skinframe->hasalpha = false;
3697         // fence textures
3698         if (name[0] == '{')
3699                 skinframe->hasalpha = true;
3700         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3701         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3702         skinframe->qgeneratemerged = true;
3703         skinframe->qgeneratebase = skinframe->qhascolormapping;
3704         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3705
3706         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3707         //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]);
3708
3709         return skinframe;
3710 }
3711
3712 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3713 {
3714         int width;
3715         int height;
3716         unsigned char *skindata;
3717         char vabuf[1024];
3718
3719         if (!skinframe->qpixels)
3720                 return;
3721
3722         if (!skinframe->qhascolormapping)
3723                 colormapped = false;
3724
3725         if (colormapped)
3726         {
3727                 if (!skinframe->qgeneratebase)
3728                         return;
3729         }
3730         else
3731         {
3732                 if (!skinframe->qgeneratemerged)
3733                         return;
3734         }
3735
3736         width = skinframe->qwidth;
3737         height = skinframe->qheight;
3738         skindata = skinframe->qpixels;
3739
3740         if (skinframe->qgeneratenmap)
3741         {
3742                 unsigned char *temp1, *temp2;
3743                 skinframe->qgeneratenmap = false;
3744                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3745                 temp2 = temp1 + width * height * 4;
3746                 // use either a custom palette or the quake palette
3747                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3748                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3749                 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);
3750                 Mem_Free(temp1);
3751         }
3752
3753         if (skinframe->qgenerateglow)
3754         {
3755                 skinframe->qgenerateglow = false;
3756                 if (skinframe->hasalpha) // fence textures
3757                         skinframe->glow = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_glow", skinframe->basename), width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags | TEXF_ALPHA, -1, palette_bgra_onlyfullbrights_transparent); // glow
3758                 else
3759                         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
3760         }
3761
3762         if (colormapped)
3763         {
3764                 skinframe->qgeneratebase = false;
3765                 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);
3766                 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);
3767                 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);
3768         }
3769         else
3770         {
3771                 skinframe->qgeneratemerged = false;
3772                 if (skinframe->hasalpha) // fence textures
3773                         skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags | TEXF_ALPHA, -1, skinframe->glow ? palette_bgra_nofullbrights_transparent : palette_bgra_transparent);
3774                 else
3775                         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);
3776         }
3777
3778         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3779         {
3780                 Mem_Free(skinframe->qpixels);
3781                 skinframe->qpixels = NULL;
3782         }
3783 }
3784
3785 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)
3786 {
3787         int i;
3788         skinframe_t *skinframe;
3789         char vabuf[1024];
3790
3791         if (cls.state == ca_dedicated)
3792                 return NULL;
3793
3794         // if already loaded just return it, otherwise make a new skinframe
3795         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3796         if (skinframe->base)
3797                 return skinframe;
3798         textureflags &= ~TEXF_FORCE_RELOAD;
3799
3800         skinframe->stain = NULL;
3801         skinframe->merged = NULL;
3802         skinframe->base = NULL;
3803         skinframe->pants = NULL;
3804         skinframe->shirt = NULL;
3805         skinframe->nmap = NULL;
3806         skinframe->gloss = NULL;
3807         skinframe->glow = NULL;
3808         skinframe->fog = NULL;
3809         skinframe->reflect = NULL;
3810         skinframe->hasalpha = false;
3811
3812         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3813         if (!skindata)
3814                 return NULL;
3815
3816         if (developer_loading.integer)
3817                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3818
3819         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3820         if (textureflags & TEXF_ALPHA)
3821         {
3822                 for (i = 0;i < width * height;i++)
3823                 {
3824                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3825                         {
3826                                 skinframe->hasalpha = true;
3827                                 break;
3828                         }
3829                 }
3830                 if (r_loadfog && skinframe->hasalpha)
3831                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3832         }
3833
3834         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3835         //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]);
3836
3837         return skinframe;
3838 }
3839
3840 skinframe_t *R_SkinFrame_LoadMissing(void)
3841 {
3842         skinframe_t *skinframe;
3843
3844         if (cls.state == ca_dedicated)
3845                 return NULL;
3846
3847         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3848         skinframe->stain = NULL;
3849         skinframe->merged = NULL;
3850         skinframe->base = NULL;
3851         skinframe->pants = NULL;
3852         skinframe->shirt = NULL;
3853         skinframe->nmap = NULL;
3854         skinframe->gloss = NULL;
3855         skinframe->glow = NULL;
3856         skinframe->fog = NULL;
3857         skinframe->reflect = NULL;
3858         skinframe->hasalpha = false;
3859
3860         skinframe->avgcolor[0] = rand() / RAND_MAX;
3861         skinframe->avgcolor[1] = rand() / RAND_MAX;
3862         skinframe->avgcolor[2] = rand() / RAND_MAX;
3863         skinframe->avgcolor[3] = 1;
3864
3865         return skinframe;
3866 }
3867
3868 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3869 typedef struct suffixinfo_s
3870 {
3871         const char *suffix;
3872         qboolean flipx, flipy, flipdiagonal;
3873 }
3874 suffixinfo_t;
3875 static suffixinfo_t suffix[3][6] =
3876 {
3877         {
3878                 {"px",   false, false, false},
3879                 {"nx",   false, false, false},
3880                 {"py",   false, false, false},
3881                 {"ny",   false, false, false},
3882                 {"pz",   false, false, false},
3883                 {"nz",   false, false, false}
3884         },
3885         {
3886                 {"posx", false, false, false},
3887                 {"negx", false, false, false},
3888                 {"posy", false, false, false},
3889                 {"negy", false, false, false},
3890                 {"posz", false, false, false},
3891                 {"negz", false, false, false}
3892         },
3893         {
3894                 {"rt",    true, false,  true},
3895                 {"lf",   false,  true,  true},
3896                 {"ft",    true,  true, false},
3897                 {"bk",   false, false, false},
3898                 {"up",    true, false,  true},
3899                 {"dn",    true, false,  true}
3900         }
3901 };
3902
3903 static int componentorder[4] = {0, 1, 2, 3};
3904
3905 static rtexture_t *R_LoadCubemap(const char *basename)
3906 {
3907         int i, j, cubemapsize;
3908         unsigned char *cubemappixels, *image_buffer;
3909         rtexture_t *cubemaptexture;
3910         char name[256];
3911         // must start 0 so the first loadimagepixels has no requested width/height
3912         cubemapsize = 0;
3913         cubemappixels = NULL;
3914         cubemaptexture = NULL;
3915         // keep trying different suffix groups (posx, px, rt) until one loads
3916         for (j = 0;j < 3 && !cubemappixels;j++)
3917         {
3918                 // load the 6 images in the suffix group
3919                 for (i = 0;i < 6;i++)
3920                 {
3921                         // generate an image name based on the base and and suffix
3922                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3923                         // load it
3924                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3925                         {
3926                                 // an image loaded, make sure width and height are equal
3927                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3928                                 {
3929                                         // if this is the first image to load successfully, allocate the cubemap memory
3930                                         if (!cubemappixels && image_width >= 1)
3931                                         {
3932                                                 cubemapsize = image_width;
3933                                                 // note this clears to black, so unavailable sides are black
3934                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3935                                         }
3936                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3937                                         if (cubemappixels)
3938                                                 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);
3939                                 }
3940                                 else
3941                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3942                                 // free the image
3943                                 Mem_Free(image_buffer);
3944                         }
3945                 }
3946         }
3947         // if a cubemap loaded, upload it
3948         if (cubemappixels)
3949         {
3950                 if (developer_loading.integer)
3951                         Con_Printf("loading cubemap \"%s\"\n", basename);
3952
3953                 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);
3954                 Mem_Free(cubemappixels);
3955         }
3956         else
3957         {
3958                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3959                 if (developer_loading.integer)
3960                 {
3961                         Con_Printf("(tried tried images ");
3962                         for (j = 0;j < 3;j++)
3963                                 for (i = 0;i < 6;i++)
3964                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3965                         Con_Print(" and was unable to find any of them).\n");
3966                 }
3967         }
3968         return cubemaptexture;
3969 }
3970
3971 rtexture_t *R_GetCubemap(const char *basename)
3972 {
3973         int i;
3974         for (i = 0;i < r_texture_numcubemaps;i++)
3975                 if (r_texture_cubemaps[i] != NULL)
3976                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3977                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3978         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3979                 return r_texture_whitecube;
3980         r_texture_numcubemaps++;
3981         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3982         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3983         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3984         return r_texture_cubemaps[i]->texture;
3985 }
3986
3987 static void R_Main_FreeViewCache(void)
3988 {
3989         if (r_refdef.viewcache.entityvisible)
3990                 Mem_Free(r_refdef.viewcache.entityvisible);
3991         if (r_refdef.viewcache.world_pvsbits)
3992                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3993         if (r_refdef.viewcache.world_leafvisible)
3994                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3995         if (r_refdef.viewcache.world_surfacevisible)
3996                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3997         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3998 }
3999
4000 static void R_Main_ResizeViewCache(void)
4001 {
4002         int numentities = r_refdef.scene.numentities;
4003         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
4004         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
4005         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
4006         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
4007         if (r_refdef.viewcache.maxentities < numentities)
4008         {
4009                 r_refdef.viewcache.maxentities = numentities;
4010                 if (r_refdef.viewcache.entityvisible)
4011                         Mem_Free(r_refdef.viewcache.entityvisible);
4012                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
4013         }
4014         if (r_refdef.viewcache.world_numclusters != numclusters)
4015         {
4016                 r_refdef.viewcache.world_numclusters = numclusters;
4017                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
4018                 if (r_refdef.viewcache.world_pvsbits)
4019                         Mem_Free(r_refdef.viewcache.world_pvsbits);
4020                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4021         }
4022         if (r_refdef.viewcache.world_numleafs != numleafs)
4023         {
4024                 r_refdef.viewcache.world_numleafs = numleafs;
4025                 if (r_refdef.viewcache.world_leafvisible)
4026                         Mem_Free(r_refdef.viewcache.world_leafvisible);
4027                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4028         }
4029         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4030         {
4031                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4032                 if (r_refdef.viewcache.world_surfacevisible)
4033                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4034                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4035         }
4036 }
4037
4038 extern rtexture_t *loadingscreentexture;
4039 static void gl_main_start(void)
4040 {
4041         loadingscreentexture = NULL;
4042         r_texture_blanknormalmap = NULL;
4043         r_texture_white = NULL;
4044         r_texture_grey128 = NULL;
4045         r_texture_black = NULL;
4046         r_texture_whitecube = NULL;
4047         r_texture_normalizationcube = NULL;
4048         r_texture_fogattenuation = NULL;
4049         r_texture_fogheighttexture = NULL;
4050         r_texture_gammaramps = NULL;
4051         r_texture_numcubemaps = 0;
4052         r_uniformbufferalignment = 32;
4053
4054         r_loaddds = r_texture_dds_load.integer != 0;
4055         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4056
4057         switch(vid.renderpath)
4058         {
4059         case RENDERPATH_GL20:
4060         case RENDERPATH_D3D9:
4061         case RENDERPATH_D3D10:
4062         case RENDERPATH_D3D11:
4063         case RENDERPATH_SOFT:
4064         case RENDERPATH_GLES2:
4065                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4066                 Cvar_SetValueQuick(&gl_combine, 1);
4067                 Cvar_SetValueQuick(&r_glsl, 1);
4068                 r_loadnormalmap = true;
4069                 r_loadgloss = true;
4070                 r_loadfog = false;
4071 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4072                 if (vid.support.arb_uniform_buffer_object)
4073                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4074 #endif
4075                         break;
4076         case RENDERPATH_GL13:
4077         case RENDERPATH_GLES1:
4078                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4079                 Cvar_SetValueQuick(&gl_combine, 1);
4080                 Cvar_SetValueQuick(&r_glsl, 0);
4081                 r_loadnormalmap = false;
4082                 r_loadgloss = false;
4083                 r_loadfog = true;
4084                 break;
4085         case RENDERPATH_GL11:
4086                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4087                 Cvar_SetValueQuick(&gl_combine, 0);
4088                 Cvar_SetValueQuick(&r_glsl, 0);
4089                 r_loadnormalmap = false;
4090                 r_loadgloss = false;
4091                 r_loadfog = true;
4092                 break;
4093         }
4094
4095         R_AnimCache_Free();
4096         R_FrameData_Reset();
4097         R_BufferData_Reset();
4098
4099         r_numqueries = 0;
4100         r_maxqueries = 0;
4101         memset(r_queries, 0, sizeof(r_queries));
4102
4103         r_qwskincache = NULL;
4104         r_qwskincache_size = 0;
4105
4106         // due to caching of texture_t references, the collision cache must be reset
4107         Collision_Cache_Reset(true);
4108
4109         // set up r_skinframe loading system for textures
4110         memset(&r_skinframe, 0, sizeof(r_skinframe));
4111         r_skinframe.loadsequence = 1;
4112         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4113
4114         r_main_texturepool = R_AllocTexturePool();
4115         R_BuildBlankTextures();
4116         R_BuildNoTexture();
4117         if (vid.support.arb_texture_cube_map)
4118         {
4119                 R_BuildWhiteCube();
4120                 R_BuildNormalizationCube();
4121         }
4122         r_texture_fogattenuation = NULL;
4123         r_texture_fogheighttexture = NULL;
4124         r_texture_gammaramps = NULL;
4125         //r_texture_fogintensity = NULL;
4126         memset(&r_fb, 0, sizeof(r_fb));
4127         r_glsl_permutation = NULL;
4128         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4129         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4130         glslshaderstring = NULL;
4131 #ifdef SUPPORTD3D
4132         r_hlsl_permutation = NULL;
4133         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4134         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4135 #endif
4136         hlslshaderstring = NULL;
4137         memset(&r_svbsp, 0, sizeof (r_svbsp));
4138
4139         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4140         r_texture_numcubemaps = 0;
4141
4142         r_refdef.fogmasktable_density = 0;
4143
4144 #ifdef __ANDROID__
4145         // For Steelstorm Android
4146         // FIXME CACHE the program and reload
4147         // FIXME see possible combinations for SS:BR android
4148         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4149         R_SetupShader_SetPermutationGLSL(0, 12);
4150         R_SetupShader_SetPermutationGLSL(0, 13);
4151         R_SetupShader_SetPermutationGLSL(0, 8388621);
4152         R_SetupShader_SetPermutationGLSL(3, 0);
4153         R_SetupShader_SetPermutationGLSL(3, 2048);
4154         R_SetupShader_SetPermutationGLSL(5, 0);
4155         R_SetupShader_SetPermutationGLSL(5, 2);
4156         R_SetupShader_SetPermutationGLSL(5, 2048);
4157         R_SetupShader_SetPermutationGLSL(5, 8388608);
4158         R_SetupShader_SetPermutationGLSL(11, 1);
4159         R_SetupShader_SetPermutationGLSL(11, 2049);
4160         R_SetupShader_SetPermutationGLSL(11, 8193);
4161         R_SetupShader_SetPermutationGLSL(11, 10241);
4162         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4163 #endif
4164 }
4165
4166 static void gl_main_shutdown(void)
4167 {
4168         R_AnimCache_Free();
4169         R_FrameData_Reset();
4170         R_BufferData_Reset();
4171
4172         R_Main_FreeViewCache();
4173
4174         switch(vid.renderpath)
4175         {
4176         case RENDERPATH_GL11:
4177         case RENDERPATH_GL13:
4178         case RENDERPATH_GL20:
4179         case RENDERPATH_GLES1:
4180         case RENDERPATH_GLES2:
4181 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4182                 if (r_maxqueries)
4183                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4184 #endif
4185                 break;
4186         case RENDERPATH_D3D9:
4187                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4188                 break;
4189         case RENDERPATH_D3D10:
4190                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4191                 break;
4192         case RENDERPATH_D3D11:
4193                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4194                 break;
4195         case RENDERPATH_SOFT:
4196                 break;
4197         }
4198
4199         r_numqueries = 0;
4200         r_maxqueries = 0;
4201         memset(r_queries, 0, sizeof(r_queries));
4202
4203         r_qwskincache = NULL;
4204         r_qwskincache_size = 0;
4205
4206         // clear out the r_skinframe state
4207         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4208         memset(&r_skinframe, 0, sizeof(r_skinframe));
4209
4210         if (r_svbsp.nodes)
4211                 Mem_Free(r_svbsp.nodes);
4212         memset(&r_svbsp, 0, sizeof (r_svbsp));
4213         R_FreeTexturePool(&r_main_texturepool);
4214         loadingscreentexture = NULL;
4215         r_texture_blanknormalmap = NULL;
4216         r_texture_white = NULL;
4217         r_texture_grey128 = NULL;
4218         r_texture_black = NULL;
4219         r_texture_whitecube = NULL;
4220         r_texture_normalizationcube = NULL;
4221         r_texture_fogattenuation = NULL;
4222         r_texture_fogheighttexture = NULL;
4223         r_texture_gammaramps = NULL;
4224         r_texture_numcubemaps = 0;
4225         //r_texture_fogintensity = NULL;
4226         memset(&r_fb, 0, sizeof(r_fb));
4227         R_GLSL_Restart_f();
4228
4229         r_glsl_permutation = NULL;
4230         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4231         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4232         glslshaderstring = NULL;
4233 #ifdef SUPPORTD3D
4234         r_hlsl_permutation = NULL;
4235         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4236         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4237 #endif
4238         hlslshaderstring = NULL;
4239 }
4240
4241 static void gl_main_newmap(void)
4242 {
4243         // FIXME: move this code to client
4244         char *entities, entname[MAX_QPATH];
4245         if (r_qwskincache)
4246                 Mem_Free(r_qwskincache);
4247         r_qwskincache = NULL;
4248         r_qwskincache_size = 0;
4249         if (cl.worldmodel)
4250         {
4251                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4252                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4253                 {
4254                         CL_ParseEntityLump(entities);
4255                         Mem_Free(entities);
4256                         return;
4257                 }
4258                 if (cl.worldmodel->brush.entities)
4259                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4260         }
4261         R_Main_FreeViewCache();
4262
4263         R_FrameData_Reset();
4264         R_BufferData_Reset();
4265 }
4266
4267 void GL_Main_Init(void)
4268 {
4269         int i;
4270         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4271
4272         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4273         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4274         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4275         if (gamemode == GAME_NEHAHRA)
4276         {
4277                 Cvar_RegisterVariable (&gl_fogenable);
4278                 Cvar_RegisterVariable (&gl_fogdensity);
4279                 Cvar_RegisterVariable (&gl_fogred);
4280                 Cvar_RegisterVariable (&gl_foggreen);
4281                 Cvar_RegisterVariable (&gl_fogblue);
4282                 Cvar_RegisterVariable (&gl_fogstart);
4283                 Cvar_RegisterVariable (&gl_fogend);
4284                 Cvar_RegisterVariable (&gl_skyclip);
4285         }
4286         Cvar_RegisterVariable(&r_motionblur);
4287         Cvar_RegisterVariable(&r_damageblur);
4288         Cvar_RegisterVariable(&r_motionblur_averaging);
4289         Cvar_RegisterVariable(&r_motionblur_randomize);
4290         Cvar_RegisterVariable(&r_motionblur_minblur);
4291         Cvar_RegisterVariable(&r_motionblur_maxblur);
4292         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4293         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4294         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4295         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4296         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4297         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4298         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4299         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4300         Cvar_RegisterVariable(&r_equalize_entities_by);
4301         Cvar_RegisterVariable(&r_equalize_entities_to);
4302         Cvar_RegisterVariable(&r_depthfirst);
4303         Cvar_RegisterVariable(&r_useinfinitefarclip);
4304         Cvar_RegisterVariable(&r_farclip_base);
4305         Cvar_RegisterVariable(&r_farclip_world);
4306         Cvar_RegisterVariable(&r_nearclip);
4307         Cvar_RegisterVariable(&r_deformvertexes);
4308         Cvar_RegisterVariable(&r_transparent);
4309         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4310         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4311         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4312         Cvar_RegisterVariable(&r_showoverdraw);
4313         Cvar_RegisterVariable(&r_showbboxes);
4314         Cvar_RegisterVariable(&r_showsurfaces);
4315         Cvar_RegisterVariable(&r_showtris);
4316         Cvar_RegisterVariable(&r_shownormals);
4317         Cvar_RegisterVariable(&r_showlighting);
4318         Cvar_RegisterVariable(&r_showshadowvolumes);
4319         Cvar_RegisterVariable(&r_showcollisionbrushes);
4320         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4321         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4322         Cvar_RegisterVariable(&r_showdisabledepthtest);
4323         Cvar_RegisterVariable(&r_drawportals);
4324         Cvar_RegisterVariable(&r_drawentities);
4325         Cvar_RegisterVariable(&r_draw2d);
4326         Cvar_RegisterVariable(&r_drawworld);
4327         Cvar_RegisterVariable(&r_cullentities_trace);
4328         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4329         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4330         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4331         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4332         Cvar_RegisterVariable(&r_sortentities);
4333         Cvar_RegisterVariable(&r_drawviewmodel);
4334         Cvar_RegisterVariable(&r_drawexteriormodel);
4335         Cvar_RegisterVariable(&r_speeds);
4336         Cvar_RegisterVariable(&r_fullbrights);
4337         Cvar_RegisterVariable(&r_wateralpha);
4338         Cvar_RegisterVariable(&r_dynamic);
4339         Cvar_RegisterVariable(&r_fakelight);
4340         Cvar_RegisterVariable(&r_fakelight_intensity);
4341         Cvar_RegisterVariable(&r_fullbright);
4342         Cvar_RegisterVariable(&r_shadows);
4343         Cvar_RegisterVariable(&r_shadows_darken);
4344         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4345         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4346         Cvar_RegisterVariable(&r_shadows_throwdistance);
4347         Cvar_RegisterVariable(&r_shadows_throwdirection);
4348         Cvar_RegisterVariable(&r_shadows_focus);
4349         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4350         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4351         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4352         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4353         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4354         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4355         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4356         Cvar_RegisterVariable(&r_fog_exp2);
4357         Cvar_RegisterVariable(&r_fog_clear);
4358         Cvar_RegisterVariable(&r_drawfog);
4359         Cvar_RegisterVariable(&r_transparentdepthmasking);
4360         Cvar_RegisterVariable(&r_transparent_sortmindist);
4361         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4362         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4363         Cvar_RegisterVariable(&r_texture_dds_load);
4364         Cvar_RegisterVariable(&r_texture_dds_save);
4365         Cvar_RegisterVariable(&r_textureunits);
4366         Cvar_RegisterVariable(&gl_combine);
4367         Cvar_RegisterVariable(&r_usedepthtextures);
4368         Cvar_RegisterVariable(&r_viewfbo);
4369         Cvar_RegisterVariable(&r_viewscale);
4370         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4371         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4372         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4373         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4374         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4375         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4376         Cvar_RegisterVariable(&r_glsl);
4377         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4378         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4379         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4380         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4381         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4382         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4383         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4384         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4385         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4386         Cvar_RegisterVariable(&r_glsl_postprocess);
4387         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4388         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4389         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4390         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4391         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4392         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4393         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4394         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4395         Cvar_RegisterVariable(&r_celshading);
4396         Cvar_RegisterVariable(&r_celoutlines);
4397
4398         Cvar_RegisterVariable(&r_water);
4399         Cvar_RegisterVariable(&r_water_cameraentitiesonly);
4400         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4401         Cvar_RegisterVariable(&r_water_clippingplanebias);
4402         Cvar_RegisterVariable(&r_water_refractdistort);
4403         Cvar_RegisterVariable(&r_water_reflectdistort);
4404         Cvar_RegisterVariable(&r_water_scissormode);
4405         Cvar_RegisterVariable(&r_water_lowquality);
4406         Cvar_RegisterVariable(&r_water_hideplayer);
4407         Cvar_RegisterVariable(&r_water_fbo);
4408
4409         Cvar_RegisterVariable(&r_lerpsprites);
4410         Cvar_RegisterVariable(&r_lerpmodels);
4411         Cvar_RegisterVariable(&r_lerplightstyles);
4412         Cvar_RegisterVariable(&r_waterscroll);
4413         Cvar_RegisterVariable(&r_bloom);
4414         Cvar_RegisterVariable(&r_bloom_colorscale);
4415         Cvar_RegisterVariable(&r_bloom_brighten);
4416         Cvar_RegisterVariable(&r_bloom_blur);
4417         Cvar_RegisterVariable(&r_bloom_resolution);
4418         Cvar_RegisterVariable(&r_bloom_colorexponent);
4419         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4420         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4421         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4422         Cvar_RegisterVariable(&r_hdr_glowintensity);
4423         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4424         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4425         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4426         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4427         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4428         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4429         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4430         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4431         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4432         Cvar_RegisterVariable(&developer_texturelogging);
4433         Cvar_RegisterVariable(&gl_lightmaps);
4434         Cvar_RegisterVariable(&r_test);
4435         Cvar_RegisterVariable(&r_batch_multidraw);
4436         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4437         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4438         Cvar_RegisterVariable(&r_glsl_skeletal);
4439         Cvar_RegisterVariable(&r_glsl_saturation);
4440         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4441         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4442         Cvar_RegisterVariable(&r_framedatasize);
4443         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4444                 Cvar_RegisterVariable(&r_buffermegs[i]);
4445         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4446         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4447                 Cvar_SetValue("r_fullbrights", 0);
4448 #ifdef DP_MOBILETOUCH
4449         // GLES devices have terrible depth precision in general, so...
4450         Cvar_SetValueQuick(&r_nearclip, 4);
4451         Cvar_SetValueQuick(&r_farclip_base, 4096);
4452         Cvar_SetValueQuick(&r_farclip_world, 0);
4453         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4454 #endif
4455         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4456 }
4457
4458 void Render_Init(void)
4459 {
4460         gl_backend_init();
4461         R_Textures_Init();
4462         GL_Main_Init();
4463         Font_Init();
4464         GL_Draw_Init();
4465         R_Shadow_Init();
4466         R_Sky_Init();
4467         GL_Surf_Init();
4468         Sbar_Init();
4469         R_Particles_Init();
4470         R_Explosion_Init();
4471         R_LightningBeams_Init();
4472         Mod_RenderInit();
4473 }
4474
4475 /*
4476 ===============
4477 GL_Init
4478 ===============
4479 */
4480 #ifndef USE_GLES2
4481 extern char *ENGINE_EXTENSIONS;
4482 void GL_Init (void)
4483 {
4484         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4485         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4486         gl_version = (const char *)qglGetString(GL_VERSION);
4487         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4488
4489         if (!gl_extensions)
4490                 gl_extensions = "";
4491         if (!gl_platformextensions)
4492                 gl_platformextensions = "";
4493
4494         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4495         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4496         Con_Printf("GL_VERSION: %s\n", gl_version);
4497         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4498         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4499
4500         VID_CheckExtensions();
4501
4502         // LordHavoc: report supported extensions
4503 #ifdef CONFIG_MENU
4504         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4505 #else
4506         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4507 #endif
4508
4509         // clear to black (loading plaque will be seen over this)
4510         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4511 }
4512 #endif
4513
4514 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4515 {
4516         int i;
4517         mplane_t *p;
4518         if (r_trippy.integer)
4519                 return false;
4520         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4521         {
4522                 p = r_refdef.view.frustum + i;
4523                 switch(p->signbits)
4524                 {
4525                 default:
4526                 case 0:
4527                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4528                                 return true;
4529                         break;
4530                 case 1:
4531                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4532                                 return true;
4533                         break;
4534                 case 2:
4535                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4536                                 return true;
4537                         break;
4538                 case 3:
4539                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4540                                 return true;
4541                         break;
4542                 case 4:
4543                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4544                                 return true;
4545                         break;
4546                 case 5:
4547                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4548                                 return true;
4549                         break;
4550                 case 6:
4551                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4552                                 return true;
4553                         break;
4554                 case 7:
4555                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4556                                 return true;
4557                         break;
4558                 }
4559         }
4560         return false;
4561 }
4562
4563 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4564 {
4565         int i;
4566         const mplane_t *p;
4567         if (r_trippy.integer)
4568                 return false;
4569         for (i = 0;i < numplanes;i++)
4570         {
4571                 p = planes + i;
4572                 switch(p->signbits)
4573                 {
4574                 default:
4575                 case 0:
4576                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4577                                 return true;
4578                         break;
4579                 case 1:
4580                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4581                                 return true;
4582                         break;
4583                 case 2:
4584                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4585                                 return true;
4586                         break;
4587                 case 3:
4588                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4589                                 return true;
4590                         break;
4591                 case 4:
4592                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4593                                 return true;
4594                         break;
4595                 case 5:
4596                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4597                                 return true;
4598                         break;
4599                 case 6:
4600                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4601                                 return true;
4602                         break;
4603                 case 7:
4604                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4605                                 return true;
4606                         break;
4607                 }
4608         }
4609         return false;
4610 }
4611
4612 //==================================================================================
4613
4614 // LordHavoc: this stores temporary data used within the same frame
4615
4616 typedef struct r_framedata_mem_s
4617 {
4618         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4619         size_t size; // how much usable space
4620         size_t current; // how much space in use
4621         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4622         size_t wantedsize; // how much space was allocated
4623         unsigned char *data; // start of real data (16byte aligned)
4624 }
4625 r_framedata_mem_t;
4626
4627 static r_framedata_mem_t *r_framedata_mem;
4628
4629 void R_FrameData_Reset(void)
4630 {
4631         while (r_framedata_mem)
4632         {
4633                 r_framedata_mem_t *next = r_framedata_mem->purge;
4634                 Mem_Free(r_framedata_mem);
4635                 r_framedata_mem = next;
4636         }
4637 }
4638
4639 static void R_FrameData_Resize(qboolean mustgrow)
4640 {
4641         size_t wantedsize;
4642         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4643         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4644         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4645         {
4646                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4647                 newmem->wantedsize = wantedsize;
4648                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4649                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4650                 newmem->current = 0;
4651                 newmem->mark = 0;
4652                 newmem->purge = r_framedata_mem;
4653                 r_framedata_mem = newmem;
4654         }
4655 }
4656
4657 void R_FrameData_NewFrame(void)
4658 {
4659         R_FrameData_Resize(false);
4660         if (!r_framedata_mem)
4661                 return;
4662         // if we ran out of space on the last frame, free the old memory now
4663         while (r_framedata_mem->purge)
4664         {
4665                 // repeatedly remove the second item in the list, leaving only head
4666                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4667                 Mem_Free(r_framedata_mem->purge);
4668                 r_framedata_mem->purge = next;
4669         }
4670         // reset the current mem pointer
4671         r_framedata_mem->current = 0;
4672         r_framedata_mem->mark = 0;
4673 }
4674
4675 void *R_FrameData_Alloc(size_t size)
4676 {
4677         void *data;
4678         float newvalue;
4679
4680         // align to 16 byte boundary - the data pointer is already aligned, so we
4681         // only need to ensure the size of every allocation is also aligned
4682         size = (size + 15) & ~15;
4683
4684         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4685         {
4686                 // emergency - we ran out of space, allocate more memory
4687                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4688                 // this might not be a growing it, but we'll allocate another buffer every time
4689                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4690                 R_FrameData_Resize(true);
4691         }
4692
4693         data = r_framedata_mem->data + r_framedata_mem->current;
4694         r_framedata_mem->current += size;
4695
4696         // count the usage for stats
4697         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4698         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4699
4700         return (void *)data;
4701 }
4702
4703 void *R_FrameData_Store(size_t size, void *data)
4704 {
4705         void *d = R_FrameData_Alloc(size);
4706         if (d && data)
4707                 memcpy(d, data, size);
4708         return d;
4709 }
4710
4711 void R_FrameData_SetMark(void)
4712 {
4713         if (!r_framedata_mem)
4714                 return;
4715         r_framedata_mem->mark = r_framedata_mem->current;
4716 }
4717
4718 void R_FrameData_ReturnToMark(void)
4719 {
4720         if (!r_framedata_mem)
4721                 return;
4722         r_framedata_mem->current = r_framedata_mem->mark;
4723 }
4724
4725 //==================================================================================
4726
4727 // avoid reusing the same buffer objects on consecutive frames
4728 #define R_BUFFERDATA_CYCLE 3
4729
4730 typedef struct r_bufferdata_buffer_s
4731 {
4732         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4733         size_t size; // how much usable space
4734         size_t current; // how much space in use
4735         r_meshbuffer_t *buffer; // the buffer itself
4736 }
4737 r_bufferdata_buffer_t;
4738
4739 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4740 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4741
4742 /// frees all dynamic buffers
4743 void R_BufferData_Reset(void)
4744 {
4745         int cycle, type;
4746         r_bufferdata_buffer_t **p, *mem;
4747         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4748         {
4749                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4750                 {
4751                         // free all buffers
4752                         p = &r_bufferdata_buffer[cycle][type];
4753                         while (*p)
4754                         {
4755                                 mem = *p;
4756                                 *p = (*p)->purge;
4757                                 if (mem->buffer)
4758                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4759                                 Mem_Free(mem);
4760                         }
4761                 }
4762         }
4763 }
4764
4765 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4766 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4767 {
4768         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4769         size_t size;
4770         float newvalue = r_buffermegs[type].value;
4771
4772         // increase the cvar if we have to (but only if we already have a mem)
4773         if (mustgrow && mem)
4774                 newvalue *= 2.0f;
4775         newvalue = bound(0.25f, newvalue, 256.0f);
4776         while (newvalue * 1024*1024 < minsize)
4777                 newvalue *= 2.0f;
4778
4779         // clamp the cvar to valid range
4780         newvalue = bound(0.25f, newvalue, 256.0f);
4781         if (r_buffermegs[type].value != newvalue)
4782                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4783
4784         // calculate size in bytes
4785         size = (size_t)(newvalue * 1024*1024);
4786         size = bound(131072, size, 256*1024*1024);
4787
4788         // allocate a new buffer if the size is different (purge old one later)
4789         // or if we were told we must grow the buffer
4790         if (!mem || mem->size != size || mustgrow)
4791         {
4792                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4793                 mem->size = size;
4794                 mem->current = 0;
4795                 if (type == R_BUFFERDATA_VERTEX)
4796                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4797                 else if (type == R_BUFFERDATA_INDEX16)
4798                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4799                 else if (type == R_BUFFERDATA_INDEX32)
4800                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4801                 else if (type == R_BUFFERDATA_UNIFORM)
4802                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4803                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4804                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4805         }
4806 }
4807
4808 void R_BufferData_NewFrame(void)
4809 {
4810         int type;
4811         r_bufferdata_buffer_t **p, *mem;
4812         // cycle to the next frame's buffers
4813         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4814         // if we ran out of space on the last time we used these buffers, free the old memory now
4815         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4816         {
4817                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4818                 {
4819                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4820                         // free all but the head buffer, this is how we recycle obsolete
4821                         // buffers after they are no longer in use
4822                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4823                         while (*p)
4824                         {
4825                                 mem = *p;
4826                                 *p = (*p)->purge;
4827                                 if (mem->buffer)
4828                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4829                                 Mem_Free(mem);
4830                         }
4831                         // reset the current offset
4832                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4833                 }
4834         }
4835 }
4836
4837 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4838 {
4839         r_bufferdata_buffer_t *mem;
4840         int offset = 0;
4841         int padsize;
4842
4843         *returnbufferoffset = 0;
4844
4845         // align size to a byte boundary appropriate for the buffer type, this
4846         // makes all allocations have aligned start offsets
4847         if (type == R_BUFFERDATA_UNIFORM)
4848                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4849         else
4850                 padsize = (datasize + 15) & ~15;
4851
4852         // if we ran out of space in this buffer we must allocate a new one
4853         if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4854                 R_BufferData_Resize(type, true, padsize);
4855
4856         // if the resize did not give us enough memory, fail
4857         if (!r_bufferdata_buffer[r_bufferdata_cycle][type] || r_bufferdata_buffer[r_bufferdata_cycle][type]->current + padsize > r_bufferdata_buffer[r_bufferdata_cycle][type]->size)
4858                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4859
4860         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4861         offset = (int)mem->current;
4862         mem->current += padsize;
4863
4864         // upload the data to the buffer at the chosen offset
4865         if (offset == 0)
4866                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4867         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4868
4869         // count the usage for stats
4870         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4871         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4872
4873         // return the buffer offset
4874         *returnbufferoffset = offset;
4875
4876         return mem->buffer;
4877 }
4878
4879 //==================================================================================
4880
4881 // LordHavoc: animcache originally written by Echon, rewritten since then
4882
4883 /**
4884  * Animation cache prevents re-generating mesh data for an animated model
4885  * multiple times in one frame for lighting, shadowing, reflections, etc.
4886  */
4887
4888 void R_AnimCache_Free(void)
4889 {
4890 }
4891
4892 void R_AnimCache_ClearCache(void)
4893 {
4894         int i;
4895         entity_render_t *ent;
4896
4897         for (i = 0;i < r_refdef.scene.numentities;i++)
4898         {
4899                 ent = r_refdef.scene.entities[i];
4900                 ent->animcache_vertex3f = NULL;
4901                 ent->animcache_vertex3f_vertexbuffer = NULL;
4902                 ent->animcache_vertex3f_bufferoffset = 0;
4903                 ent->animcache_normal3f = NULL;
4904                 ent->animcache_normal3f_vertexbuffer = NULL;
4905                 ent->animcache_normal3f_bufferoffset = 0;
4906                 ent->animcache_svector3f = NULL;
4907                 ent->animcache_svector3f_vertexbuffer = NULL;
4908                 ent->animcache_svector3f_bufferoffset = 0;
4909                 ent->animcache_tvector3f = NULL;
4910                 ent->animcache_tvector3f_vertexbuffer = NULL;
4911                 ent->animcache_tvector3f_bufferoffset = 0;
4912                 ent->animcache_vertexmesh = NULL;
4913                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4914                 ent->animcache_vertexmesh_bufferoffset = 0;
4915                 ent->animcache_skeletaltransform3x4 = NULL;
4916                 ent->animcache_skeletaltransform3x4buffer = NULL;
4917                 ent->animcache_skeletaltransform3x4offset = 0;
4918                 ent->animcache_skeletaltransform3x4size = 0;
4919         }
4920 }
4921
4922 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4923 {
4924         int i;
4925
4926         // check if we need the meshbuffers
4927         if (!vid.useinterleavedarrays)
4928                 return;
4929
4930         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4931                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4932         // TODO: upload vertexbuffer?
4933         if (ent->animcache_vertexmesh)
4934         {
4935                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4936                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4937                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4938                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4939                 for (i = 0;i < numvertices;i++)
4940                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4941                 if (ent->animcache_svector3f)
4942                         for (i = 0;i < numvertices;i++)
4943                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4944                 if (ent->animcache_tvector3f)
4945                         for (i = 0;i < numvertices;i++)
4946                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4947                 if (ent->animcache_normal3f)
4948                         for (i = 0;i < numvertices;i++)
4949                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4950         }
4951 }
4952
4953 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4954 {
4955         dp_model_t *model = ent->model;
4956         int numvertices;
4957
4958         // see if this ent is worth caching
4959         if (!model || !model->Draw || !model->AnimateVertices)
4960                 return false;
4961         // nothing to cache if it contains no animations and has no skeleton
4962         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4963                 return false;
4964         // see if it is already cached for gpuskeletal
4965         if (ent->animcache_skeletaltransform3x4)
4966                 return false;
4967         // see if it is already cached as a mesh
4968         if (ent->animcache_vertex3f)
4969         {
4970                 // check if we need to add normals or tangents
4971                 if (ent->animcache_normal3f)
4972                         wantnormals = false;
4973                 if (ent->animcache_svector3f)
4974                         wanttangents = false;
4975                 if (!wantnormals && !wanttangents)
4976                         return false;
4977         }
4978
4979         // check which kind of cache we need to generate
4980         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4981         {
4982                 // cache the skeleton so the vertex shader can use it
4983                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4984                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4985                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4986                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4987                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4988                 // note: this can fail if the buffer is at the grow limit
4989                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4990                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4991         }
4992         else if (ent->animcache_vertex3f)
4993         {
4994                 // mesh was already cached but we may need to add normals/tangents
4995                 // (this only happens with multiple views, reflections, cameras, etc)
4996                 if (wantnormals || wanttangents)
4997                 {
4998                         numvertices = model->surfmesh.num_vertices;
4999                         if (wantnormals)
5000                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5001                         if (wanttangents)
5002                         {
5003                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5004                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5005                         }
5006                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
5007                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5008                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5009                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5010                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5011                 }
5012         }
5013         else
5014         {
5015                 // generate mesh cache
5016                 numvertices = model->surfmesh.num_vertices;
5017                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5018                 if (wantnormals)
5019                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5020                 if (wanttangents)
5021                 {
5022                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5023                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5024                 }
5025                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5026                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5027                 if (wantnormals || wanttangents)
5028                 {
5029                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5030                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5031                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5032                 }
5033                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5034                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5035                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5036         }
5037         return true;
5038 }
5039
5040 void R_AnimCache_CacheVisibleEntities(void)
5041 {
5042         int i;
5043         qboolean wantnormals = true;
5044         qboolean wanttangents = !r_showsurfaces.integer;
5045
5046         switch(vid.renderpath)
5047         {
5048         case RENDERPATH_GL20:
5049         case RENDERPATH_D3D9:
5050         case RENDERPATH_D3D10:
5051         case RENDERPATH_D3D11:
5052         case RENDERPATH_GLES2:
5053                 break;
5054         case RENDERPATH_GL11:
5055         case RENDERPATH_GL13:
5056         case RENDERPATH_GLES1:
5057                 wanttangents = false;
5058                 break;
5059         case RENDERPATH_SOFT:
5060                 break;
5061         }
5062
5063         if (r_shownormals.integer)
5064                 wanttangents = wantnormals = true;
5065
5066         // TODO: thread this
5067         // NOTE: R_PrepareRTLights() also caches entities
5068
5069         for (i = 0;i < r_refdef.scene.numentities;i++)
5070                 if (r_refdef.viewcache.entityvisible[i])
5071                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5072 }
5073
5074 //==================================================================================
5075
5076 extern cvar_t r_overheadsprites_pushback;
5077
5078 static void R_View_UpdateEntityLighting (void)
5079 {
5080         int i;
5081         entity_render_t *ent;
5082         vec3_t tempdiffusenormal, avg;
5083         vec_t f, fa, fd, fdd;
5084         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5085
5086         for (i = 0;i < r_refdef.scene.numentities;i++)
5087         {
5088                 ent = r_refdef.scene.entities[i];
5089
5090                 // skip unseen models
5091                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5092                         continue;
5093
5094                 // skip bsp models
5095                 if (ent->model && ent->model == cl.worldmodel)
5096                 {
5097                         // TODO: use modellight for r_ambient settings on world?
5098                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5099                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5100                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5101                         continue;
5102                 }
5103                 
5104                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5105                 {
5106                         // aleady updated by CSQC
5107                         // TODO: force modellight on BSP models in this case?
5108                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5109                 }
5110                 else
5111                 {
5112                         // fetch the lighting from the worldmodel data
5113                         VectorClear(ent->modellight_ambient);
5114                         VectorClear(ent->modellight_diffuse);
5115                         VectorClear(tempdiffusenormal);
5116                         if (ent->flags & RENDER_LIGHT)
5117                         {
5118                                 vec3_t org;
5119                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5120
5121                                 // complete lightning for lit sprites
5122                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5123                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5124                                 {
5125                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5126                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5127                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5128                                 }
5129                                 else
5130                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5131
5132                                 if(ent->flags & RENDER_EQUALIZE)
5133                                 {
5134                                         // first fix up ambient lighting...
5135                                         if(r_equalize_entities_minambient.value > 0)
5136                                         {
5137                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5138                                                 if(fd > 0)
5139                                                 {
5140                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5141                                                         if(fa < r_equalize_entities_minambient.value * fd)
5142                                                         {
5143                                                                 // solve:
5144                                                                 //   fa'/fd' = minambient
5145                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5146                                                                 //   ...
5147                                                                 //   fa' = fd' * minambient
5148                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5149                                                                 //   ...
5150                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5151                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5152                                                                 //   ...
5153                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5154                                                                 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
5155                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5156                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5157                                                         }
5158                                                 }
5159                                         }
5160
5161                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5162                                         {
5163                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5164                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5165                                                 f = fa + 0.25 * fd;
5166                                                 if(f > 0)
5167                                                 {
5168                                                         // adjust brightness and saturation to target
5169                                                         avg[0] = avg[1] = avg[2] = fa / f;
5170                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5171                                                         avg[0] = avg[1] = avg[2] = fd / f;
5172                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5173                                                 }
5174                                         }
5175                                 }
5176                         }
5177                         else // highly rare
5178                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5179                 }
5180
5181                 // move the light direction into modelspace coordinates for lighting code
5182                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5183                 if(VectorLength2(ent->modellight_lightdir) == 0)
5184                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5185                 VectorNormalize(ent->modellight_lightdir);
5186         }
5187 }
5188
5189 #define MAX_LINEOFSIGHTTRACES 64
5190
5191 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5192 {
5193         int i;
5194         vec3_t boxmins, boxmaxs;
5195         vec3_t start;
5196         vec3_t end;
5197         dp_model_t *model = r_refdef.scene.worldmodel;
5198
5199         if (!model || !model->brush.TraceLineOfSight)
5200                 return true;
5201
5202         // expand the box a little
5203         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5204         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5205         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5206         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5207         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5208         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5209
5210         // return true if eye is inside enlarged box
5211         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5212                 return true;
5213
5214         // try center
5215         VectorCopy(eye, start);
5216         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5217         if (model->brush.TraceLineOfSight(model, start, end))
5218                 return true;
5219
5220         // try various random positions
5221         for (i = 0;i < numsamples;i++)
5222         {
5223                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5224                 if (model->brush.TraceLineOfSight(model, start, end))
5225                         return true;
5226         }
5227
5228         return false;
5229 }
5230
5231
5232 static void R_View_UpdateEntityVisible (void)
5233 {
5234         int i;
5235         int renderimask;
5236         int samples;
5237         entity_render_t *ent;
5238
5239         if (r_refdef.envmap || r_fb.water.hideplayer)
5240                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5241         else if (chase_active.integer || r_fb.water.renderingscene)
5242                 renderimask = RENDER_VIEWMODEL;
5243         else
5244                 renderimask = RENDER_EXTERIORMODEL;
5245         if (!r_drawviewmodel.integer)
5246                 renderimask |= RENDER_VIEWMODEL;
5247         if (!r_drawexteriormodel.integer)
5248                 renderimask |= RENDER_EXTERIORMODEL;
5249         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5250         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5251         {
5252                 // worldmodel can check visibility
5253                 for (i = 0;i < r_refdef.scene.numentities;i++)
5254                 {
5255                         ent = r_refdef.scene.entities[i];
5256                         if (!(ent->flags & renderimask))
5257                         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)))
5258                         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))
5259                                 r_refdef.viewcache.entityvisible[i] = true;
5260                 }
5261         }
5262         else
5263         {
5264                 // no worldmodel or it can't check visibility
5265                 for (i = 0;i < r_refdef.scene.numentities;i++)
5266                 {
5267                         ent = r_refdef.scene.entities[i];
5268                         if (!(ent->flags & renderimask))
5269                         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)))
5270                                 r_refdef.viewcache.entityvisible[i] = true;
5271                 }
5272         }
5273         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5274                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5275         {
5276                 for (i = 0;i < r_refdef.scene.numentities;i++)
5277                 {
5278                         if (!r_refdef.viewcache.entityvisible[i])
5279                                 continue;
5280                         ent = r_refdef.scene.entities[i];
5281                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5282                         {
5283                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5284                                 if (samples < 0)
5285                                         continue; // temp entities do pvs only
5286                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5287                                         ent->last_trace_visibility = realtime;
5288                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5289                                         r_refdef.viewcache.entityvisible[i] = 0;
5290                         }
5291                 }
5292         }
5293 }
5294
5295 /// only used if skyrendermasked, and normally returns false
5296 static int R_DrawBrushModelsSky (void)
5297 {
5298         int i, sky;
5299         entity_render_t *ent;
5300
5301         sky = false;
5302         for (i = 0;i < r_refdef.scene.numentities;i++)
5303         {
5304                 if (!r_refdef.viewcache.entityvisible[i])
5305                         continue;
5306                 ent = r_refdef.scene.entities[i];
5307                 if (!ent->model || !ent->model->DrawSky)
5308                         continue;
5309                 ent->model->DrawSky(ent);
5310                 sky = true;
5311         }
5312         return sky;
5313 }
5314
5315 static void R_DrawNoModel(entity_render_t *ent);
5316 static void R_DrawModels(void)
5317 {
5318         int i;
5319         entity_render_t *ent;
5320
5321         for (i = 0;i < r_refdef.scene.numentities;i++)
5322         {
5323                 if (!r_refdef.viewcache.entityvisible[i])
5324                         continue;
5325                 ent = r_refdef.scene.entities[i];
5326                 r_refdef.stats[r_stat_entities]++;
5327                 /*
5328                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5329                 {
5330                         vec3_t f, l, u, o;
5331                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5332                         Con_Printf("R_DrawModels\n");
5333                         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]);
5334                         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);
5335                         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);
5336                 }
5337                 */
5338                 if (ent->model && ent->model->Draw != NULL)
5339                         ent->model->Draw(ent);
5340                 else
5341                         R_DrawNoModel(ent);
5342         }
5343 }
5344
5345 static void R_DrawModelsDepth(void)
5346 {
5347         int i;
5348         entity_render_t *ent;
5349
5350         for (i = 0;i < r_refdef.scene.numentities;i++)
5351         {
5352                 if (!r_refdef.viewcache.entityvisible[i])
5353                         continue;
5354                 ent = r_refdef.scene.entities[i];
5355                 if (ent->model && ent->model->DrawDepth != NULL)
5356                         ent->model->DrawDepth(ent);
5357         }
5358 }
5359
5360 static void R_DrawModelsDebug(void)
5361 {
5362         int i;
5363         entity_render_t *ent;
5364
5365         for (i = 0;i < r_refdef.scene.numentities;i++)
5366         {
5367                 if (!r_refdef.viewcache.entityvisible[i])
5368                         continue;
5369                 ent = r_refdef.scene.entities[i];
5370                 if (ent->model && ent->model->DrawDebug != NULL)
5371                         ent->model->DrawDebug(ent);
5372         }
5373 }
5374
5375 static void R_DrawModelsAddWaterPlanes(void)
5376 {
5377         int i;
5378         entity_render_t *ent;
5379
5380         for (i = 0;i < r_refdef.scene.numentities;i++)
5381         {
5382                 if (!r_refdef.viewcache.entityvisible[i])
5383                         continue;
5384                 ent = r_refdef.scene.entities[i];
5385                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5386                         ent->model->DrawAddWaterPlanes(ent);
5387         }
5388 }
5389
5390 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}};
5391
5392 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5393 {
5394         if (r_hdr_irisadaptation.integer)
5395         {
5396                 vec3_t p;
5397                 vec3_t ambient;
5398                 vec3_t diffuse;
5399                 vec3_t diffusenormal;
5400                 vec3_t forward;
5401                 vec_t brightness = 0.0f;
5402                 vec_t goal;
5403                 vec_t current;
5404                 vec_t d;
5405                 int c;
5406                 VectorCopy(r_refdef.view.forward, forward);
5407                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5408                 {
5409                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5410                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5411                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5412                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5413                         d = DotProduct(forward, diffusenormal);
5414                         brightness += VectorLength(ambient);
5415                         if (d > 0)
5416                                 brightness += d * VectorLength(diffuse);
5417                 }
5418                 brightness *= 1.0f / c;
5419                 brightness += 0.00001f; // make sure it's never zero
5420                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5421                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5422                 current = r_hdr_irisadaptation_value.value;
5423                 if (current < goal)
5424                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5425                 else if (current > goal)
5426                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5427                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5428                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5429         }
5430         else if (r_hdr_irisadaptation_value.value != 1.0f)
5431                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5432 }
5433
5434 static void R_View_SetFrustum(const int *scissor)
5435 {
5436         int i;
5437         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5438         vec3_t forward, left, up, origin, v;
5439
5440         if(scissor)
5441         {
5442                 // flipped x coordinates (because x points left here)
5443                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5444                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5445
5446                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5447                 switch(vid.renderpath)
5448                 {
5449                         case RENDERPATH_D3D9:
5450                         case RENDERPATH_D3D10:
5451                         case RENDERPATH_D3D11:
5452                                 // non-flipped y coordinates
5453                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5454                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5455                                 break;
5456                         case RENDERPATH_SOFT:
5457                         case RENDERPATH_GL11:
5458                         case RENDERPATH_GL13:
5459                         case RENDERPATH_GL20:
5460                         case RENDERPATH_GLES1:
5461                         case RENDERPATH_GLES2:
5462                                 // non-flipped y coordinates
5463                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5464                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5465                                 break;
5466                 }
5467         }
5468
5469         // we can't trust r_refdef.view.forward and friends in reflected scenes
5470         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5471
5472 #if 0
5473         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5474         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5475         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5476         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5477         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5478         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5479         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5480         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5481         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5482         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5483         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5484         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5485 #endif
5486
5487 #if 0
5488         zNear = r_refdef.nearclip;
5489         nudge = 1.0 - 1.0 / (1<<23);
5490         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5491         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5492         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5493         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5494         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5495         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5496         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5497         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5498 #endif
5499
5500
5501
5502 #if 0
5503         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5504         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5505         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5506         r_refdef.view.frustum[0].dist = m[15] - m[12];
5507
5508         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5509         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5510         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5511         r_refdef.view.frustum[1].dist = m[15] + m[12];
5512
5513         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5514         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5515         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5516         r_refdef.view.frustum[2].dist = m[15] - m[13];
5517
5518         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5519         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5520         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5521         r_refdef.view.frustum[3].dist = m[15] + m[13];
5522
5523         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5524         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5525         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5526         r_refdef.view.frustum[4].dist = m[15] - m[14];
5527
5528         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5529         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5530         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5531         r_refdef.view.frustum[5].dist = m[15] + m[14];
5532 #endif
5533
5534         if (r_refdef.view.useperspective)
5535         {
5536                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5537                 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]);
5538                 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]);
5539                 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]);
5540                 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]);
5541
5542                 // then the normals from the corners relative to origin
5543                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5544                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5545                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5546                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5547
5548                 // in a NORMAL view, forward cross left == up
5549                 // in a REFLECTED view, forward cross left == down
5550                 // so our cross products above need to be adjusted for a left handed coordinate system
5551                 CrossProduct(forward, left, v);
5552                 if(DotProduct(v, up) < 0)
5553                 {
5554                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5555                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5556                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5557                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5558                 }
5559
5560                 // Leaving those out was a mistake, those were in the old code, and they
5561                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5562                 // I couldn't reproduce it after adding those normalizations. --blub
5563                 VectorNormalize(r_refdef.view.frustum[0].normal);
5564                 VectorNormalize(r_refdef.view.frustum[1].normal);
5565                 VectorNormalize(r_refdef.view.frustum[2].normal);
5566                 VectorNormalize(r_refdef.view.frustum[3].normal);
5567
5568                 // make the corners absolute
5569                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5570                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5571                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5572                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5573
5574                 // one more normal
5575                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5576
5577                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5578                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5579                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5580                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5581                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5582         }
5583         else
5584         {
5585                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5586                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5587                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5588                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5589                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5590                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5591                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5592                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5593                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5594                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5595         }
5596         r_refdef.view.numfrustumplanes = 5;
5597
5598         if (r_refdef.view.useclipplane)
5599         {
5600                 r_refdef.view.numfrustumplanes = 6;
5601                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5602         }
5603
5604         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5605                 PlaneClassify(r_refdef.view.frustum + i);
5606
5607         // LordHavoc: note to all quake engine coders, Quake had a special case
5608         // for 90 degrees which assumed a square view (wrong), so I removed it,
5609         // Quake2 has it disabled as well.
5610
5611         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5612         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5613         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5614         //PlaneClassify(&frustum[0]);
5615
5616         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5617         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5618         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5619         //PlaneClassify(&frustum[1]);
5620
5621         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5622         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5623         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5624         //PlaneClassify(&frustum[2]);
5625
5626         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5627         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5628         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5629         //PlaneClassify(&frustum[3]);
5630
5631         // nearclip plane
5632         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5633         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5634         //PlaneClassify(&frustum[4]);
5635 }
5636
5637 static void R_View_UpdateWithScissor(const int *myscissor)
5638 {
5639         R_Main_ResizeViewCache();
5640         R_View_SetFrustum(myscissor);
5641         R_View_WorldVisibility(r_refdef.view.useclipplane);
5642         R_View_UpdateEntityVisible();
5643         R_View_UpdateEntityLighting();
5644 }
5645
5646 static void R_View_Update(void)
5647 {
5648         R_Main_ResizeViewCache();
5649         R_View_SetFrustum(NULL);
5650         R_View_WorldVisibility(r_refdef.view.useclipplane);
5651         R_View_UpdateEntityVisible();
5652         R_View_UpdateEntityLighting();
5653 }
5654
5655 float viewscalefpsadjusted = 1.0f;
5656
5657 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5658 {
5659         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5660         scale = bound(0.03125f, scale, 1.0f);
5661         *outwidth = (int)ceil(width * scale);
5662         *outheight = (int)ceil(height * scale);
5663 }
5664
5665 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5666 {
5667         const float *customclipplane = NULL;
5668         float plane[4];
5669         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5670         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5671         {
5672                 // LordHavoc: couldn't figure out how to make this approach the
5673                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5674                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5675                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5676                         dist = r_refdef.view.clipplane.dist;
5677                 plane[0] = r_refdef.view.clipplane.normal[0];
5678                 plane[1] = r_refdef.view.clipplane.normal[1];
5679                 plane[2] = r_refdef.view.clipplane.normal[2];
5680                 plane[3] = -dist;
5681                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5682         }
5683
5684         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5685         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5686
5687         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5688         if (!r_refdef.view.useperspective)
5689                 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);
5690         else if (vid.stencil && r_useinfinitefarclip.integer)
5691                 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);
5692         else
5693                 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);
5694         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5695         R_SetViewport(&r_refdef.view.viewport);
5696         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5697         {
5698                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5699                 float screenplane[4];
5700                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5701                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5702                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5703                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5704                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5705         }
5706 }
5707
5708 void R_EntityMatrix(const matrix4x4_t *matrix)
5709 {
5710         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5711         {
5712                 gl_modelmatrixchanged = false;
5713                 gl_modelmatrix = *matrix;
5714                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5715                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5716                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5717                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5718                 CHECKGLERROR
5719                 switch(vid.renderpath)
5720                 {
5721                 case RENDERPATH_D3D9:
5722 #ifdef SUPPORTD3D
5723                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5724                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5725 #endif
5726                         break;
5727                 case RENDERPATH_D3D10:
5728                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5729                         break;
5730                 case RENDERPATH_D3D11:
5731                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5732                         break;
5733                 case RENDERPATH_GL11:
5734                 case RENDERPATH_GL13:
5735                 case RENDERPATH_GLES1:
5736 #ifndef USE_GLES2
5737                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5738 #endif
5739                         break;
5740                 case RENDERPATH_SOFT:
5741                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5742                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5743                         break;
5744                 case RENDERPATH_GL20:
5745                 case RENDERPATH_GLES2:
5746                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5747                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5748                         break;
5749                 }
5750         }
5751 }
5752
5753 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5754 {
5755         r_viewport_t viewport;
5756
5757         CHECKGLERROR
5758
5759         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5760         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);
5761         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5762         R_SetViewport(&viewport);
5763         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5764         GL_Color(1, 1, 1, 1);
5765         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5766         GL_BlendFunc(GL_ONE, GL_ZERO);
5767         GL_ScissorTest(false);
5768         GL_DepthMask(false);
5769         GL_DepthRange(0, 1);
5770         GL_DepthTest(false);
5771         GL_DepthFunc(GL_LEQUAL);
5772         R_EntityMatrix(&identitymatrix);
5773         R_Mesh_ResetTextureState();
5774         GL_PolygonOffset(0, 0);
5775         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5776         switch(vid.renderpath)
5777         {
5778         case RENDERPATH_GL11:
5779         case RENDERPATH_GL13:
5780         case RENDERPATH_GL20:
5781         case RENDERPATH_GLES1:
5782         case RENDERPATH_GLES2:
5783                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5784                 break;
5785         case RENDERPATH_D3D9:
5786         case RENDERPATH_D3D10:
5787         case RENDERPATH_D3D11:
5788         case RENDERPATH_SOFT:
5789                 break;
5790         }
5791         GL_CullFace(GL_NONE);
5792
5793         CHECKGLERROR
5794 }
5795
5796 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5797 {
5798         DrawQ_Finish();
5799
5800         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5801 }
5802
5803 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5804 {
5805         DrawQ_Finish();
5806
5807         R_SetupView(true, fbo, depthtexture, colortexture);
5808         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5809         GL_Color(1, 1, 1, 1);
5810         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5811         GL_BlendFunc(GL_ONE, GL_ZERO);
5812         GL_ScissorTest(true);
5813         GL_DepthMask(true);
5814         GL_DepthRange(0, 1);
5815         GL_DepthTest(true);
5816         GL_DepthFunc(GL_LEQUAL);
5817         R_EntityMatrix(&identitymatrix);
5818         R_Mesh_ResetTextureState();
5819         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5820         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5821         switch(vid.renderpath)
5822         {
5823         case RENDERPATH_GL11:
5824         case RENDERPATH_GL13:
5825         case RENDERPATH_GL20:
5826         case RENDERPATH_GLES1:
5827         case RENDERPATH_GLES2:
5828                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5829                 break;
5830         case RENDERPATH_D3D9:
5831         case RENDERPATH_D3D10:
5832         case RENDERPATH_D3D11:
5833         case RENDERPATH_SOFT:
5834                 break;
5835         }
5836         GL_CullFace(r_refdef.view.cullface_back);
5837 }
5838
5839 /*
5840 ================
5841 R_RenderView_UpdateViewVectors
5842 ================
5843 */
5844 void R_RenderView_UpdateViewVectors(void)
5845 {
5846         // break apart the view matrix into vectors for various purposes
5847         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5848         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5849         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5850         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5851         // make an inverted copy of the view matrix for tracking sprites
5852         Matrix4x4_Invert_Full(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5853 }
5854
5855 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5856 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5857
5858 static void R_Water_StartFrame(void)
5859 {
5860         int i;
5861         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5862         r_waterstate_waterplane_t *p;
5863         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;
5864
5865         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5866                 return;
5867
5868         switch(vid.renderpath)
5869         {
5870         case RENDERPATH_GL20:
5871         case RENDERPATH_D3D9:
5872         case RENDERPATH_D3D10:
5873         case RENDERPATH_D3D11:
5874         case RENDERPATH_SOFT:
5875         case RENDERPATH_GLES2:
5876                 break;
5877         case RENDERPATH_GL11:
5878         case RENDERPATH_GL13:
5879         case RENDERPATH_GLES1:
5880                 return;
5881         }
5882
5883         // set waterwidth and waterheight to the water resolution that will be
5884         // used (often less than the screen resolution for faster rendering)
5885         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5886
5887         // calculate desired texture sizes
5888         // can't use water if the card does not support the texture size
5889         if (!r_water.integer || r_showsurfaces.integer)
5890                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5891         else if (vid.support.arb_texture_non_power_of_two)
5892         {
5893                 texturewidth = waterwidth;
5894                 textureheight = waterheight;
5895                 camerawidth = waterwidth;
5896                 cameraheight = waterheight;
5897         }
5898         else
5899         {
5900                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5901                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5902                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5903                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5904         }
5905
5906         // allocate textures as needed
5907         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))
5908         {
5909                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5910                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5911                 {
5912                         if (p->texture_refraction)
5913                                 R_FreeTexture(p->texture_refraction);
5914                         p->texture_refraction = NULL;
5915                         if (p->fbo_refraction)
5916                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5917                         p->fbo_refraction = 0;
5918                         if (p->texture_reflection)
5919                                 R_FreeTexture(p->texture_reflection);
5920                         p->texture_reflection = NULL;
5921                         if (p->fbo_reflection)
5922                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5923                         p->fbo_reflection = 0;
5924                         if (p->texture_camera)
5925                                 R_FreeTexture(p->texture_camera);
5926                         p->texture_camera = NULL;
5927                         if (p->fbo_camera)
5928                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5929                         p->fbo_camera = 0;
5930                 }
5931                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5932                 r_fb.water.texturewidth = texturewidth;
5933                 r_fb.water.textureheight = textureheight;
5934                 r_fb.water.camerawidth = camerawidth;
5935                 r_fb.water.cameraheight = cameraheight;
5936         }
5937
5938         if (r_fb.water.texturewidth)
5939         {
5940                 int scaledwidth, scaledheight;
5941
5942                 r_fb.water.enabled = true;
5943
5944                 // water resolution is usually reduced
5945                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5946                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5947                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5948
5949                 // set up variables that will be used in shader setup
5950                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5951                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5952                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5953                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5954         }
5955
5956         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5957         r_fb.water.numwaterplanes = 0;
5958 }
5959
5960 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5961 {
5962         int planeindex, bestplaneindex, vertexindex;
5963         vec3_t mins, maxs, normal, center, v, n;
5964         vec_t planescore, bestplanescore;
5965         mplane_t plane;
5966         r_waterstate_waterplane_t *p;
5967         texture_t *t = R_GetCurrentTexture(surface->texture);
5968
5969         rsurface.texture = t;
5970         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5971         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5972         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5973                 return;
5974         // average the vertex normals, find the surface bounds (after deformvertexes)
5975         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5976         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5977         VectorCopy(n, normal);
5978         VectorCopy(v, mins);
5979         VectorCopy(v, maxs);
5980         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5981         {
5982                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5983                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5984                 VectorAdd(normal, n, normal);
5985                 mins[0] = min(mins[0], v[0]);
5986                 mins[1] = min(mins[1], v[1]);
5987                 mins[2] = min(mins[2], v[2]);
5988                 maxs[0] = max(maxs[0], v[0]);
5989                 maxs[1] = max(maxs[1], v[1]);
5990                 maxs[2] = max(maxs[2], v[2]);
5991         }
5992         VectorNormalize(normal);
5993         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5994
5995         VectorCopy(normal, plane.normal);
5996         VectorNormalize(plane.normal);
5997         plane.dist = DotProduct(center, plane.normal);
5998         PlaneClassify(&plane);
5999         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
6000         {
6001                 // skip backfaces (except if nocullface is set)
6002 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
6003 //                      return;
6004                 VectorNegate(plane.normal, plane.normal);
6005                 plane.dist *= -1;
6006                 PlaneClassify(&plane);
6007         }
6008
6009
6010         // find a matching plane if there is one
6011         bestplaneindex = -1;
6012         bestplanescore = 1048576.0f;
6013         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6014         {
6015                 if(p->camera_entity == t->camera_entity)
6016                 {
6017                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
6018                         if (bestplaneindex < 0 || bestplanescore > planescore)
6019                         {
6020                                 bestplaneindex = planeindex;
6021                                 bestplanescore = planescore;
6022                         }
6023                 }
6024         }
6025         planeindex = bestplaneindex;
6026
6027         // if this surface does not fit any known plane rendered this frame, add one
6028         if (planeindex < 0 || bestplanescore > 0.001f)
6029         {
6030                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6031                 {
6032                         // store the new plane
6033                         planeindex = r_fb.water.numwaterplanes++;
6034                         p = r_fb.water.waterplanes + planeindex;
6035                         p->plane = plane;
6036                         // clear materialflags and pvs
6037                         p->materialflags = 0;
6038                         p->pvsvalid = false;
6039                         p->camera_entity = t->camera_entity;
6040                         VectorCopy(mins, p->mins);
6041                         VectorCopy(maxs, p->maxs);
6042                 }
6043                 else
6044                 {
6045                         // We're totally screwed.
6046                         return;
6047                 }
6048         }
6049         else
6050         {
6051                 // merge mins/maxs when we're adding this surface to the plane
6052                 p = r_fb.water.waterplanes + planeindex;
6053                 p->mins[0] = min(p->mins[0], mins[0]);
6054                 p->mins[1] = min(p->mins[1], mins[1]);
6055                 p->mins[2] = min(p->mins[2], mins[2]);
6056                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6057                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6058                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6059         }
6060         // merge this surface's materialflags into the waterplane
6061         p->materialflags |= t->currentmaterialflags;
6062         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6063         {
6064                 // merge this surface's PVS into the waterplane
6065                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6066                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6067                 {
6068                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6069                         p->pvsvalid = true;
6070                 }
6071         }
6072 }
6073
6074 extern cvar_t r_drawparticles;
6075 extern cvar_t r_drawdecals;
6076
6077 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6078 {
6079         int myscissor[4];
6080         r_refdef_view_t originalview;
6081         r_refdef_view_t myview;
6082         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;
6083         r_waterstate_waterplane_t *p;
6084         vec3_t visorigin;
6085         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;
6086         char vabuf[1024];
6087
6088         originalview = r_refdef.view;
6089
6090         // lowquality hack, temporarily shut down some cvars and restore afterwards
6091         qualityreduction = r_water_lowquality.integer;
6092         if (qualityreduction > 0)
6093         {
6094                 if (qualityreduction >= 1)
6095                 {
6096                         old_r_shadows = r_shadows.integer;
6097                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6098                         old_r_dlight = r_shadow_realtime_dlight.integer;
6099                         Cvar_SetValueQuick(&r_shadows, 0);
6100                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6101                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6102                 }
6103                 if (qualityreduction >= 2)
6104                 {
6105                         old_r_dynamic = r_dynamic.integer;
6106                         old_r_particles = r_drawparticles.integer;
6107                         old_r_decals = r_drawdecals.integer;
6108                         Cvar_SetValueQuick(&r_dynamic, 0);
6109                         Cvar_SetValueQuick(&r_drawparticles, 0);
6110                         Cvar_SetValueQuick(&r_drawdecals, 0);
6111                 }
6112         }
6113
6114         // make sure enough textures are allocated
6115         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6116         {
6117                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6118                         continue;
6119                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6120                 {
6121                         if (!p->texture_refraction)
6122                                 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);
6123                         if (!p->texture_refraction)
6124                                 goto error;
6125                         if (usewaterfbo)
6126                         {
6127                                 if (r_fb.water.depthtexture == NULL)
6128                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6129                                 if (p->fbo_refraction == 0)
6130                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6131                         }
6132                 }
6133                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6134                 {
6135                         if (!p->texture_camera)
6136                                 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);
6137                         if (!p->texture_camera)
6138                                 goto error;
6139                         if (usewaterfbo)
6140                         {
6141                                 if (r_fb.water.depthtexture == NULL)
6142                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6143                                 if (p->fbo_camera == 0)
6144                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6145                         }
6146                 }
6147
6148                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6149                 {
6150                         if (!p->texture_reflection)
6151                                 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);
6152                         if (!p->texture_reflection)
6153                                 goto error;
6154                         if (usewaterfbo)
6155                         {
6156                                 if (r_fb.water.depthtexture == NULL)
6157                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6158                                 if (p->fbo_reflection == 0)
6159                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6160                         }
6161                 }
6162         }
6163
6164         // render views
6165         r_refdef.view = originalview;
6166         r_refdef.view.showdebug = false;
6167         r_refdef.view.width = r_fb.water.waterwidth;
6168         r_refdef.view.height = r_fb.water.waterheight;
6169         r_refdef.view.useclipplane = true;
6170         myview = r_refdef.view;
6171         r_fb.water.renderingscene = true;
6172         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6173         {
6174                 if (r_water_cameraentitiesonly.value != 0 && !p->camera_entity)
6175                         continue;
6176                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6177                 {
6178                         r_refdef.view = myview;
6179                         if(r_water_scissormode.integer)
6180                         {
6181                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6182                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6183                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6184                         }
6185
6186                         // render reflected scene and copy into texture
6187                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6188                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6189                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6190                         r_refdef.view.clipplane = p->plane;
6191                         // reverse the cullface settings for this render
6192                         r_refdef.view.cullface_front = GL_FRONT;
6193                         r_refdef.view.cullface_back = GL_BACK;
6194                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6195                         {
6196                                 r_refdef.view.usecustompvs = true;
6197                                 if (p->pvsvalid)
6198                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6199                                 else
6200                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6201                         }
6202
6203                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6204                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6205                         R_ClearScreen(r_refdef.fogenabled);
6206                         if(r_water_scissormode.integer & 2)
6207                                 R_View_UpdateWithScissor(myscissor);
6208                         else
6209                                 R_View_Update();
6210                         R_AnimCache_CacheVisibleEntities();
6211                         if(r_water_scissormode.integer & 1)
6212                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6213                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6214
6215                         if (!p->fbo_reflection)
6216                                 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);
6217                         r_fb.water.hideplayer = false;
6218                 }
6219
6220                 // render the normal view scene and copy into texture
6221                 // (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)
6222                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6223                 {
6224                         r_refdef.view = myview;
6225                         if(r_water_scissormode.integer)
6226                         {
6227                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6228                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6229                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6230                         }
6231
6232                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6233
6234                         r_refdef.view.clipplane = p->plane;
6235                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6236                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6237
6238                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6239                         {
6240                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6241                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6242                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6243                                 R_RenderView_UpdateViewVectors();
6244                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6245                                 {
6246                                         r_refdef.view.usecustompvs = true;
6247                                         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);
6248                                 }
6249                         }
6250
6251                         PlaneClassify(&r_refdef.view.clipplane);
6252
6253                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6254                         R_ClearScreen(r_refdef.fogenabled);
6255                         if(r_water_scissormode.integer & 2)
6256                                 R_View_UpdateWithScissor(myscissor);
6257                         else
6258                                 R_View_Update();
6259                         R_AnimCache_CacheVisibleEntities();
6260                         if(r_water_scissormode.integer & 1)
6261                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6262                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6263
6264                         if (!p->fbo_refraction)
6265                                 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);
6266                         r_fb.water.hideplayer = false;
6267                 }
6268                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6269                 {
6270                         r_refdef.view = myview;
6271
6272                         r_refdef.view.clipplane = p->plane;
6273                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6274                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6275
6276                         r_refdef.view.width = r_fb.water.camerawidth;
6277                         r_refdef.view.height = r_fb.water.cameraheight;
6278                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6279                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6280                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6281                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6282
6283                         if(p->camera_entity)
6284                         {
6285                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6286                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6287                         }
6288
6289                         // note: all of the view is used for displaying... so
6290                         // there is no use in scissoring
6291
6292                         // reverse the cullface settings for this render
6293                         r_refdef.view.cullface_front = GL_FRONT;
6294                         r_refdef.view.cullface_back = GL_BACK;
6295                         // also reverse the view matrix
6296                         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
6297                         R_RenderView_UpdateViewVectors();
6298                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6299                         {
6300                                 r_refdef.view.usecustompvs = true;
6301                                 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);
6302                         }
6303                         
6304                         // camera needs no clipplane
6305                         r_refdef.view.useclipplane = false;
6306
6307                         PlaneClassify(&r_refdef.view.clipplane);
6308
6309                         r_fb.water.hideplayer = false;
6310
6311                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6312                         R_ClearScreen(r_refdef.fogenabled);
6313                         R_View_Update();
6314                         R_AnimCache_CacheVisibleEntities();
6315                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6316
6317                         if (!p->fbo_camera)
6318                                 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);
6319                         r_fb.water.hideplayer = false;
6320                 }
6321
6322         }
6323         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6324         r_fb.water.renderingscene = false;
6325         r_refdef.view = originalview;
6326         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6327         if (!r_fb.water.depthtexture)
6328                 R_ClearScreen(r_refdef.fogenabled);
6329         R_View_Update();
6330         R_AnimCache_CacheVisibleEntities();
6331         goto finish;
6332 error:
6333         r_refdef.view = originalview;
6334         r_fb.water.renderingscene = false;
6335         Cvar_SetValueQuick(&r_water, 0);
6336         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6337 finish:
6338         // lowquality hack, restore cvars
6339         if (qualityreduction > 0)
6340         {
6341                 if (qualityreduction >= 1)
6342                 {
6343                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6344                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6345                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6346                 }
6347                 if (qualityreduction >= 2)
6348                 {
6349                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6350                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6351                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6352                 }
6353         }
6354 }
6355
6356 static void R_Bloom_StartFrame(void)
6357 {
6358         int i;
6359         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6360         int viewwidth, viewheight;
6361         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6362         textype_t textype = TEXTYPE_COLORBUFFER;
6363
6364         switch (vid.renderpath)
6365         {
6366         case RENDERPATH_GL20:
6367                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6368                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6369                 {
6370                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6371                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6372                 }
6373                 break;
6374         case RENDERPATH_GL11:
6375         case RENDERPATH_GL13:
6376         case RENDERPATH_GLES1:
6377         case RENDERPATH_GLES2:
6378         case RENDERPATH_D3D9:
6379         case RENDERPATH_D3D10:
6380         case RENDERPATH_D3D11:
6381                 r_fb.usedepthtextures = false;
6382                 break;
6383         case RENDERPATH_SOFT:
6384                 r_fb.usedepthtextures = true;
6385                 break;
6386         }
6387
6388         if (r_viewscale_fpsscaling.integer)
6389         {
6390                 double actualframetime;
6391                 double targetframetime;
6392                 double adjust;
6393                 actualframetime = r_refdef.lastdrawscreentime;
6394                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6395                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6396                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6397                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6398                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6399                 viewscalefpsadjusted += adjust;
6400                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6401         }
6402         else
6403                 viewscalefpsadjusted = 1.0f;
6404
6405         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6406
6407         switch(vid.renderpath)
6408         {
6409         case RENDERPATH_GL20:
6410         case RENDERPATH_D3D9:
6411         case RENDERPATH_D3D10:
6412         case RENDERPATH_D3D11:
6413         case RENDERPATH_SOFT:
6414         case RENDERPATH_GLES2:
6415                 break;
6416         case RENDERPATH_GL11:
6417         case RENDERPATH_GL13:
6418         case RENDERPATH_GLES1:
6419                 return;
6420         }
6421
6422         // set bloomwidth and bloomheight to the bloom resolution that will be
6423         // used (often less than the screen resolution for faster rendering)
6424         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6425         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6426         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6427         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6428         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6429
6430         // calculate desired texture sizes
6431         if (vid.support.arb_texture_non_power_of_two)
6432         {
6433                 screentexturewidth = vid.width;
6434                 screentextureheight = vid.height;
6435                 bloomtexturewidth = r_fb.bloomwidth;
6436                 bloomtextureheight = r_fb.bloomheight;
6437         }
6438         else
6439         {
6440                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6441                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6442                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6443                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6444         }
6445
6446         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))
6447         {
6448                 Cvar_SetValueQuick(&r_bloom, 0);
6449                 Cvar_SetValueQuick(&r_motionblur, 0);
6450                 Cvar_SetValueQuick(&r_damageblur, 0);
6451         }
6452
6453         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6454          && !r_bloom.integer
6455          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6456          && !useviewfbo
6457          && r_viewscale.value == 1.0f
6458          && !r_viewscale_fpsscaling.integer)
6459                 screentexturewidth = screentextureheight = 0;
6460         if (!r_bloom.integer)
6461                 bloomtexturewidth = bloomtextureheight = 0;
6462
6463         // allocate textures as needed
6464         if (r_fb.screentexturewidth != screentexturewidth
6465          || r_fb.screentextureheight != screentextureheight
6466          || r_fb.bloomtexturewidth != bloomtexturewidth
6467          || r_fb.bloomtextureheight != bloomtextureheight
6468          || r_fb.textype != textype
6469          || useviewfbo != (r_fb.fbo != 0))
6470         {
6471                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6472                 {
6473                         if (r_fb.bloomtexture[i])
6474                                 R_FreeTexture(r_fb.bloomtexture[i]);
6475                         r_fb.bloomtexture[i] = NULL;
6476
6477                         if (r_fb.bloomfbo[i])
6478                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6479                         r_fb.bloomfbo[i] = 0;
6480                 }
6481
6482                 if (r_fb.fbo)
6483                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6484                 r_fb.fbo = 0;
6485
6486                 if (r_fb.colortexture)
6487                         R_FreeTexture(r_fb.colortexture);
6488                 r_fb.colortexture = NULL;
6489
6490                 if (r_fb.depthtexture)
6491                         R_FreeTexture(r_fb.depthtexture);
6492                 r_fb.depthtexture = NULL;
6493
6494                 if (r_fb.ghosttexture)
6495                         R_FreeTexture(r_fb.ghosttexture);
6496                 r_fb.ghosttexture = NULL;
6497
6498                 r_fb.screentexturewidth = screentexturewidth;
6499                 r_fb.screentextureheight = screentextureheight;
6500                 r_fb.bloomtexturewidth = bloomtexturewidth;
6501                 r_fb.bloomtextureheight = bloomtextureheight;
6502                 r_fb.textype = textype;
6503
6504                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6505                 {
6506                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6507                                 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);
6508                         r_fb.ghosttexture_valid = false;
6509                         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);
6510                         if (useviewfbo)
6511                         {
6512                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6513                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6514                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6515                         }
6516                 }
6517
6518                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6519                 {
6520                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6521                         {
6522                                 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);
6523                                 if (useviewfbo)
6524                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6525                         }
6526                 }
6527         }
6528
6529         // bloom texture is a different resolution
6530         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6531         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6532         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6533         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6534         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6535
6536         // set up a texcoord array for the full resolution screen image
6537         // (we have to keep this around to copy back during final render)
6538         r_fb.screentexcoord2f[0] = 0;
6539         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6540         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6541         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6542         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6543         r_fb.screentexcoord2f[5] = 0;
6544         r_fb.screentexcoord2f[6] = 0;
6545         r_fb.screentexcoord2f[7] = 0;
6546
6547         if(r_fb.fbo) 
6548         {
6549                 for (i = 1;i < 8;i += 2)
6550                 {
6551                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6552                 }
6553         }
6554
6555         // set up a texcoord array for the reduced resolution bloom image
6556         // (which will be additive blended over the screen image)
6557         r_fb.bloomtexcoord2f[0] = 0;
6558         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6559         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6560         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6561         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6562         r_fb.bloomtexcoord2f[5] = 0;
6563         r_fb.bloomtexcoord2f[6] = 0;
6564         r_fb.bloomtexcoord2f[7] = 0;
6565
6566         switch(vid.renderpath)
6567         {
6568         case RENDERPATH_GL11:
6569         case RENDERPATH_GL13:
6570         case RENDERPATH_GL20:
6571         case RENDERPATH_SOFT:
6572         case RENDERPATH_GLES1:
6573         case RENDERPATH_GLES2:
6574                 break;
6575         case RENDERPATH_D3D9:
6576         case RENDERPATH_D3D10:
6577         case RENDERPATH_D3D11:
6578                 for (i = 0;i < 4;i++)
6579                 {
6580                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6581                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6582                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6583                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6584                 }
6585                 break;
6586         }
6587
6588         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6589
6590         if (r_fb.fbo)
6591                 r_refdef.view.clear = true;
6592 }
6593
6594 static void R_Bloom_MakeTexture(void)
6595 {
6596         int x, range, dir;
6597         float xoffset, yoffset, r, brighten;
6598         rtexture_t *intex;
6599         float colorscale = r_bloom_colorscale.value;
6600
6601         r_refdef.stats[r_stat_bloom]++;
6602     
6603 #if 0
6604     // this copy is unnecessary since it happens in R_BlendView already
6605         if (!r_fb.fbo)
6606         {
6607                 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);
6608                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6609         }
6610 #endif
6611
6612         // scale down screen texture to the bloom texture size
6613         CHECKGLERROR
6614         r_fb.bloomindex = 0;
6615         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6616         R_SetViewport(&r_fb.bloomviewport);
6617         GL_DepthTest(false);
6618         GL_BlendFunc(GL_ONE, GL_ZERO);
6619         GL_Color(colorscale, colorscale, colorscale, 1);
6620         // 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...
6621         switch(vid.renderpath)
6622         {
6623         case RENDERPATH_GL11:
6624         case RENDERPATH_GL13:
6625         case RENDERPATH_GL20:
6626         case RENDERPATH_GLES1:
6627         case RENDERPATH_GLES2:
6628         case RENDERPATH_SOFT:
6629                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6630                 break;
6631         case RENDERPATH_D3D9:
6632         case RENDERPATH_D3D10:
6633         case RENDERPATH_D3D11:
6634                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6635                 break;
6636         }
6637         // TODO: do boxfilter scale-down in shader?
6638         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6639         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6640         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6641
6642         // we now have a properly scaled bloom image
6643         if (!r_fb.bloomfbo[r_fb.bloomindex])
6644         {
6645                 // copy it into the bloom texture
6646                 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);
6647                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6648         }
6649
6650         // multiply bloom image by itself as many times as desired
6651         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6652         {
6653                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6654                 r_fb.bloomindex ^= 1;
6655                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6656                 x *= 2;
6657                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6658                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6659                 {
6660                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6661                         GL_Color(r,r,r,1); // apply fix factor
6662                 }
6663                 else
6664                 {
6665                         if(x <= 2)
6666                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6667                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6668                         GL_Color(1,1,1,1); // no fix factor supported here
6669                 }
6670                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6671                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6672                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6673                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6674
6675                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6676                 {
6677                         // copy the darkened image to a texture
6678                         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);
6679                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6680                 }
6681         }
6682
6683         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6684         brighten = r_bloom_brighten.value;
6685         brighten = sqrt(brighten);
6686         if(range >= 1)
6687                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6688
6689         for (dir = 0;dir < 2;dir++)
6690         {
6691                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6692                 r_fb.bloomindex ^= 1;
6693                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6694                 // blend on at multiple vertical offsets to achieve a vertical blur
6695                 // TODO: do offset blends using GLSL
6696                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6697                 GL_BlendFunc(GL_ONE, GL_ZERO);
6698                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6699                 for (x = -range;x <= range;x++)
6700                 {
6701                         if (!dir){xoffset = 0;yoffset = x;}
6702                         else {xoffset = x;yoffset = 0;}
6703                         xoffset /= (float)r_fb.bloomtexturewidth;
6704                         yoffset /= (float)r_fb.bloomtextureheight;
6705                         // compute a texcoord array with the specified x and y offset
6706                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6707                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6708                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6709                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6710                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6711                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6712                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6713                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6714                         // this r value looks like a 'dot' particle, fading sharply to
6715                         // black at the edges
6716                         // (probably not realistic but looks good enough)
6717                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6718                         //r = brighten/(range*2+1);
6719                         r = brighten / (range * 2 + 1);
6720                         if(range >= 1)
6721                                 r *= (1 - x*x/(float)(range*range));
6722                         GL_Color(r, r, r, 1);
6723                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6724                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6725                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6726                         GL_BlendFunc(GL_ONE, GL_ONE);
6727                 }
6728
6729                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6730                 {
6731                         // copy the vertically or horizontally blurred bloom view to a texture
6732                         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);
6733                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6734                 }
6735         }
6736 }
6737
6738 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6739 {
6740         unsigned int permutation;
6741         float uservecs[4][4];
6742
6743         R_EntityMatrix(&identitymatrix);
6744
6745         switch (vid.renderpath)
6746         {
6747         case RENDERPATH_GL20:
6748         case RENDERPATH_D3D9:
6749         case RENDERPATH_D3D10:
6750         case RENDERPATH_D3D11:
6751         case RENDERPATH_SOFT:
6752         case RENDERPATH_GLES2:
6753                 permutation =
6754                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6755                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6756                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6757                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6758                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6759
6760                 if (r_fb.colortexture)
6761                 {
6762                         if (!r_fb.fbo)
6763                         {
6764                                 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);
6765                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6766                         }
6767
6768                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6769                         {
6770                                 // declare variables
6771                                 float blur_factor, blur_mouseaccel, blur_velocity;
6772                                 static float blur_average; 
6773                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6774
6775                                 // set a goal for the factoring
6776                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6777                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6778                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6779                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6780                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6781                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6782
6783                                 // from the goal, pick an averaged value between goal and last value
6784                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6785                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6786
6787                                 // enforce minimum amount of blur 
6788                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6789
6790                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6791
6792                                 // calculate values into a standard alpha
6793                                 cl.motionbluralpha = 1 - exp(-
6794                                                 (
6795                                                  (r_motionblur.value * blur_factor / 80)
6796                                                  +
6797                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6798                                                 )
6799                                                 /
6800                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6801                                           );
6802
6803                                 // randomization for the blur value to combat persistent ghosting
6804                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6805                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6806
6807                                 // apply the blur
6808                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6809                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6810                                 {
6811                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6812                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6813                                         switch(vid.renderpath)
6814                                         {
6815                                         case RENDERPATH_GL11:
6816                                         case RENDERPATH_GL13:
6817                                         case RENDERPATH_GL20:
6818                                         case RENDERPATH_GLES1:
6819                                         case RENDERPATH_GLES2:
6820                                         case RENDERPATH_SOFT:
6821                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6822                                                 break;
6823                                         case RENDERPATH_D3D9:
6824                                         case RENDERPATH_D3D10:
6825                                         case RENDERPATH_D3D11:
6826                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6827                                                 break;
6828                                         }
6829                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6830                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6831                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6832                                 }
6833
6834                                 // updates old view angles for next pass
6835                                 VectorCopy(cl.viewangles, blur_oldangles);
6836
6837                                 // copy view into the ghost texture
6838                                 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);
6839                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6840                                 r_fb.ghosttexture_valid = true;
6841                         }
6842                 }
6843                 else
6844                 {
6845                         // no r_fb.colortexture means we're rendering to the real fb
6846                         // we may still have to do view tint...
6847                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6848                         {
6849                                 // apply a color tint to the whole view
6850                                 R_ResetViewRendering2D(0, NULL, NULL);
6851                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6852                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6853                                 R_SetupShader_Generic_NoTexture(false, true);
6854                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6855                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6856                         }
6857                         break; // no screen processing, no bloom, skip it
6858                 }
6859
6860                 if (r_fb.bloomtexture[0])
6861                 {
6862                         // make the bloom texture
6863                         R_Bloom_MakeTexture();
6864                 }
6865
6866 #if _MSC_VER >= 1400
6867 #define sscanf sscanf_s
6868 #endif
6869                 memset(uservecs, 0, sizeof(uservecs));
6870                 if (r_glsl_postprocess_uservec1_enable.integer)
6871                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6872                 if (r_glsl_postprocess_uservec2_enable.integer)
6873                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6874                 if (r_glsl_postprocess_uservec3_enable.integer)
6875                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6876                 if (r_glsl_postprocess_uservec4_enable.integer)
6877                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6878
6879                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6880                 GL_Color(1, 1, 1, 1);
6881                 GL_BlendFunc(GL_ONE, GL_ZERO);
6882
6883                 switch(vid.renderpath)
6884                 {
6885                 case RENDERPATH_GL20:
6886                 case RENDERPATH_GLES2:
6887                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6888                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6889                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6890                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6891                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6892                         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]);
6893                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6894                         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]);
6895                         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]);
6896                         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]);
6897                         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]);
6898                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6899                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6900                         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);
6901                         break;
6902                 case RENDERPATH_D3D9:
6903 #ifdef SUPPORTD3D
6904                         // 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...
6905                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6906                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6907                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6908                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6909                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6910                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6911                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6912                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6913                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6914                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6915                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6916                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6917                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6918                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6919 #endif
6920                         break;
6921                 case RENDERPATH_D3D10:
6922                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6923                         break;
6924                 case RENDERPATH_D3D11:
6925                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6926                         break;
6927                 case RENDERPATH_SOFT:
6928                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6929                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6930                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6931                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6932                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6933                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6934                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6935                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6936                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6937                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6938                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6939                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6940                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6941                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6942                         break;
6943                 default:
6944                         break;
6945                 }
6946                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6947                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6948                 break;
6949         case RENDERPATH_GL11:
6950         case RENDERPATH_GL13:
6951         case RENDERPATH_GLES1:
6952                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6953                 {
6954                         // apply a color tint to the whole view
6955                         R_ResetViewRendering2D(0, NULL, NULL);
6956                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6957                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6958                         R_SetupShader_Generic_NoTexture(false, true);
6959                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6960                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6961                 }
6962                 break;
6963         }
6964 }
6965
6966 matrix4x4_t r_waterscrollmatrix;
6967
6968 void R_UpdateFog(void)
6969 {
6970         // Nehahra fog
6971         if (gamemode == GAME_NEHAHRA)
6972         {
6973                 if (gl_fogenable.integer)
6974                 {
6975                         r_refdef.oldgl_fogenable = true;
6976                         r_refdef.fog_density = gl_fogdensity.value;
6977                         r_refdef.fog_red = gl_fogred.value;
6978                         r_refdef.fog_green = gl_foggreen.value;
6979                         r_refdef.fog_blue = gl_fogblue.value;
6980                         r_refdef.fog_alpha = 1;
6981                         r_refdef.fog_start = 0;
6982                         r_refdef.fog_end = gl_skyclip.value;
6983                         r_refdef.fog_height = 1<<30;
6984                         r_refdef.fog_fadedepth = 128;
6985                 }
6986                 else if (r_refdef.oldgl_fogenable)
6987                 {
6988                         r_refdef.oldgl_fogenable = false;
6989                         r_refdef.fog_density = 0;
6990                         r_refdef.fog_red = 0;
6991                         r_refdef.fog_green = 0;
6992                         r_refdef.fog_blue = 0;
6993                         r_refdef.fog_alpha = 0;
6994                         r_refdef.fog_start = 0;
6995                         r_refdef.fog_end = 0;
6996                         r_refdef.fog_height = 1<<30;
6997                         r_refdef.fog_fadedepth = 128;
6998                 }
6999         }
7000
7001         // fog parms
7002         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
7003         r_refdef.fog_start = max(0, r_refdef.fog_start);
7004         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
7005
7006         if (r_refdef.fog_density && r_drawfog.integer)
7007         {
7008                 r_refdef.fogenabled = true;
7009                 // this is the point where the fog reaches 0.9986 alpha, which we
7010                 // consider a good enough cutoff point for the texture
7011                 // (0.9986 * 256 == 255.6)
7012                 if (r_fog_exp2.integer)
7013                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
7014                 else
7015                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
7016                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
7017                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
7018                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
7019                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
7020                         R_BuildFogHeightTexture();
7021                 // fog color was already set
7022                 // update the fog texture
7023                 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)
7024                         R_BuildFogTexture();
7025                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7026                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7027         }
7028         else
7029                 r_refdef.fogenabled = false;
7030
7031         // fog color
7032         if (r_refdef.fog_density)
7033         {
7034                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7035                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7036                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7037
7038                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7039                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7040                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7041                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7042
7043                 {
7044                         vec3_t fogvec;
7045                         VectorCopy(r_refdef.fogcolor, fogvec);
7046                         //   color.rgb *= ContrastBoost * SceneBrightness;
7047                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7048                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7049                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7050                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7051                 }
7052         }
7053 }
7054
7055 void R_UpdateVariables(void)
7056 {
7057         R_Textures_Frame();
7058
7059         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7060
7061         r_refdef.farclip = r_farclip_base.value;
7062         if (r_refdef.scene.worldmodel)
7063                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7064         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7065
7066         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7067                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7068         r_refdef.polygonfactor = 0;
7069         r_refdef.polygonoffset = 0;
7070         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7071         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7072
7073         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7074         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7075         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7076         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7077         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7078         if (FAKELIGHT_ENABLED)
7079         {
7080                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7081         }
7082         else if (r_refdef.scene.worldmodel)
7083         {
7084                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7085         }
7086         if (r_showsurfaces.integer)
7087         {
7088                 r_refdef.scene.rtworld = false;
7089                 r_refdef.scene.rtworldshadows = false;
7090                 r_refdef.scene.rtdlight = false;
7091                 r_refdef.scene.rtdlightshadows = false;
7092                 r_refdef.lightmapintensity = 0;
7093         }
7094
7095         r_gpuskeletal = false;
7096         switch(vid.renderpath)
7097         {
7098         case RENDERPATH_GL20:
7099                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7100         case RENDERPATH_D3D9:
7101         case RENDERPATH_D3D10:
7102         case RENDERPATH_D3D11:
7103         case RENDERPATH_SOFT:
7104         case RENDERPATH_GLES2:
7105                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7106                 {
7107                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7108                         {
7109                                 // build GLSL gamma texture
7110 #define RAMPWIDTH 256
7111                                 unsigned short ramp[RAMPWIDTH * 3];
7112                                 unsigned char rampbgr[RAMPWIDTH][4];
7113                                 int i;
7114
7115                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7116
7117                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7118                                 for(i = 0; i < RAMPWIDTH; ++i)
7119                                 {
7120                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7121                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7122                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7123                                         rampbgr[i][3] = 0;
7124                                 }
7125                                 if (r_texture_gammaramps)
7126                                 {
7127                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7128                                 }
7129                                 else
7130                                 {
7131                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7132                                 }
7133                         }
7134                 }
7135                 else
7136                 {
7137                         // remove GLSL gamma texture
7138                 }
7139                 break;
7140         case RENDERPATH_GL11:
7141         case RENDERPATH_GL13:
7142         case RENDERPATH_GLES1:
7143                 break;
7144         }
7145 }
7146
7147 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7148 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7149 /*
7150 ================
7151 R_SelectScene
7152 ================
7153 */
7154 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7155         if( scenetype != r_currentscenetype ) {
7156                 // store the old scenetype
7157                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7158                 r_currentscenetype = scenetype;
7159                 // move in the new scene
7160                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7161         }
7162 }
7163
7164 /*
7165 ================
7166 R_GetScenePointer
7167 ================
7168 */
7169 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7170 {
7171         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7172         if( scenetype == r_currentscenetype ) {
7173                 return &r_refdef.scene;
7174         } else {
7175                 return &r_scenes_store[ scenetype ];
7176         }
7177 }
7178
7179 static int R_SortEntities_Compare(const void *ap, const void *bp)
7180 {
7181         const entity_render_t *a = *(const entity_render_t **)ap;
7182         const entity_render_t *b = *(const entity_render_t **)bp;
7183
7184         // 1. compare model
7185         if(a->model < b->model)
7186                 return -1;
7187         if(a->model > b->model)
7188                 return +1;
7189
7190         // 2. compare skin
7191         // TODO possibly calculate the REAL skinnum here first using
7192         // skinscenes?
7193         if(a->skinnum < b->skinnum)
7194                 return -1;
7195         if(a->skinnum > b->skinnum)
7196                 return +1;
7197
7198         // everything we compared is equal
7199         return 0;
7200 }
7201 static void R_SortEntities(void)
7202 {
7203         // below or equal 2 ents, sorting never gains anything
7204         if(r_refdef.scene.numentities <= 2)
7205                 return;
7206         // sort
7207         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7208 }
7209
7210 /*
7211 ================
7212 R_RenderView
7213 ================
7214 */
7215 int dpsoftrast_test;
7216 extern cvar_t r_shadow_bouncegrid;
7217 void R_RenderView(void)
7218 {
7219         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7220         int fbo;
7221         rtexture_t *depthtexture;
7222         rtexture_t *colortexture;
7223
7224         dpsoftrast_test = r_test.integer;
7225
7226         if (r_timereport_active)
7227                 R_TimeReport("start");
7228         r_textureframe++; // used only by R_GetCurrentTexture
7229         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7230
7231         if(R_CompileShader_CheckStaticParms())
7232                 R_GLSL_Restart_f();
7233
7234         if (!r_drawentities.integer)
7235                 r_refdef.scene.numentities = 0;
7236         else if (r_sortentities.integer)
7237                 R_SortEntities();
7238
7239         R_AnimCache_ClearCache();
7240
7241         /* adjust for stereo display */
7242         if(R_Stereo_Active())
7243         {
7244                 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);
7245                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7246         }
7247
7248         if (r_refdef.view.isoverlay)
7249         {
7250                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7251                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7252                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7253                 R_TimeReport("depthclear");
7254
7255                 r_refdef.view.showdebug = false;
7256
7257                 r_fb.water.enabled = false;
7258                 r_fb.water.numwaterplanes = 0;
7259
7260                 R_RenderScene(0, NULL, NULL);
7261
7262                 r_refdef.view.matrix = originalmatrix;
7263
7264                 CHECKGLERROR
7265                 return;
7266         }
7267
7268         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7269         {
7270                 r_refdef.view.matrix = originalmatrix;
7271                 return;
7272         }
7273
7274         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7275
7276         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7277                 // in sRGB fallback, behave similar to true sRGB: convert this
7278                 // value from linear to sRGB
7279                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7280
7281         R_RenderView_UpdateViewVectors();
7282
7283         R_Shadow_UpdateWorldLightSelection();
7284
7285         R_Bloom_StartFrame();
7286
7287         // apply bloom brightness offset
7288         if(r_fb.bloomtexture[0])
7289                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7290
7291         R_Water_StartFrame();
7292
7293         // now we probably have an fbo to render into
7294         fbo = r_fb.fbo;
7295         depthtexture = r_fb.depthtexture;
7296         colortexture = r_fb.colortexture;
7297
7298         CHECKGLERROR
7299         if (r_timereport_active)
7300                 R_TimeReport("viewsetup");
7301
7302         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7303
7304         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7305         {
7306                 R_ClearScreen(r_refdef.fogenabled);
7307                 if (r_timereport_active)
7308                         R_TimeReport("viewclear");
7309         }
7310         r_refdef.view.clear = true;
7311
7312         r_refdef.view.showdebug = true;
7313
7314         R_View_Update();
7315         if (r_timereport_active)
7316                 R_TimeReport("visibility");
7317
7318         R_AnimCache_CacheVisibleEntities();
7319         if (r_timereport_active)
7320                 R_TimeReport("animcache");
7321
7322         R_Shadow_UpdateBounceGridTexture();
7323         if (r_timereport_active && r_shadow_bouncegrid.integer)
7324                 R_TimeReport("bouncegrid");
7325
7326         r_fb.water.numwaterplanes = 0;
7327         if (r_fb.water.enabled)
7328                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7329
7330         R_RenderScene(fbo, depthtexture, colortexture);
7331         r_fb.water.numwaterplanes = 0;
7332
7333         R_BlendView(fbo, depthtexture, colortexture);
7334         if (r_timereport_active)
7335                 R_TimeReport("blendview");
7336
7337         GL_Scissor(0, 0, vid.width, vid.height);
7338         GL_ScissorTest(false);
7339
7340         r_refdef.view.matrix = originalmatrix;
7341
7342         CHECKGLERROR
7343 }
7344
7345 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7346 {
7347         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7348         {
7349                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7350                 if (r_timereport_active)
7351                         R_TimeReport("waterworld");
7352         }
7353
7354         // don't let sound skip if going slow
7355         if (r_refdef.scene.extraupdate)
7356                 S_ExtraUpdate ();
7357
7358         R_DrawModelsAddWaterPlanes();
7359         if (r_timereport_active)
7360                 R_TimeReport("watermodels");
7361
7362         if (r_fb.water.numwaterplanes)
7363         {
7364                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7365                 if (r_timereport_active)
7366                         R_TimeReport("waterscenes");
7367         }
7368 }
7369
7370 extern cvar_t cl_locs_show;
7371 static void R_DrawLocs(void);
7372 static void R_DrawEntityBBoxes(void);
7373 static void R_DrawModelDecals(void);
7374 extern cvar_t cl_decals_newsystem;
7375 extern qboolean r_shadow_usingdeferredprepass;
7376 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7377 {
7378         qboolean shadowmapping = false;
7379
7380         if (r_timereport_active)
7381                 R_TimeReport("beginscene");
7382
7383         r_refdef.stats[r_stat_renders]++;
7384
7385         R_UpdateFog();
7386
7387         // don't let sound skip if going slow
7388         if (r_refdef.scene.extraupdate)
7389                 S_ExtraUpdate ();
7390
7391         R_MeshQueue_BeginScene();
7392
7393         R_SkyStartFrame();
7394
7395         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);
7396
7397         if (r_timereport_active)
7398                 R_TimeReport("skystartframe");
7399
7400         if (cl.csqc_vidvars.drawworld)
7401         {
7402                 // don't let sound skip if going slow
7403                 if (r_refdef.scene.extraupdate)
7404                         S_ExtraUpdate ();
7405
7406                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7407                 {
7408                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7409                         if (r_timereport_active)
7410                                 R_TimeReport("worldsky");
7411                 }
7412
7413                 if (R_DrawBrushModelsSky() && r_timereport_active)
7414                         R_TimeReport("bmodelsky");
7415
7416                 if (skyrendermasked && skyrenderlater)
7417                 {
7418                         // we have to force off the water clipping plane while rendering sky
7419                         R_SetupView(false, fbo, depthtexture, colortexture);
7420                         R_Sky();
7421                         R_SetupView(true, fbo, depthtexture, colortexture);
7422                         if (r_timereport_active)
7423                                 R_TimeReport("sky");
7424                 }
7425         }
7426
7427         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7428         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7429                 R_Shadow_PrepareModelShadows();
7430         if (r_timereport_active)
7431                 R_TimeReport("preparelights");
7432
7433         if (R_Shadow_ShadowMappingEnabled())
7434                 shadowmapping = true;
7435
7436         if (r_shadow_usingdeferredprepass)
7437                 R_Shadow_DrawPrepass();
7438
7439         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7440         {
7441                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7442                 if (r_timereport_active)
7443                         R_TimeReport("worlddepth");
7444         }
7445         if (r_depthfirst.integer >= 2)
7446         {
7447                 R_DrawModelsDepth();
7448                 if (r_timereport_active)
7449                         R_TimeReport("modeldepth");
7450         }
7451
7452         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7453         {
7454                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7455                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7456                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7457                 // don't let sound skip if going slow
7458                 if (r_refdef.scene.extraupdate)
7459                         S_ExtraUpdate ();
7460         }
7461
7462         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7463         {
7464                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7465                 if (r_timereport_active)
7466                         R_TimeReport("world");
7467         }
7468
7469         // don't let sound skip if going slow
7470         if (r_refdef.scene.extraupdate)
7471                 S_ExtraUpdate ();
7472
7473         R_DrawModels();
7474         if (r_timereport_active)
7475                 R_TimeReport("models");
7476
7477         // don't let sound skip if going slow
7478         if (r_refdef.scene.extraupdate)
7479                 S_ExtraUpdate ();
7480
7481         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7482         {
7483                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7484                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7485                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7486                 // don't let sound skip if going slow
7487                 if (r_refdef.scene.extraupdate)
7488                         S_ExtraUpdate ();
7489         }
7490
7491         if (!r_shadow_usingdeferredprepass)
7492         {
7493                 R_Shadow_DrawLights();
7494                 if (r_timereport_active)
7495                         R_TimeReport("rtlights");
7496         }
7497
7498         // don't let sound skip if going slow
7499         if (r_refdef.scene.extraupdate)
7500                 S_ExtraUpdate ();
7501
7502         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7503         {
7504                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7505                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7506                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7507                 // don't let sound skip if going slow
7508                 if (r_refdef.scene.extraupdate)
7509                         S_ExtraUpdate ();
7510         }
7511
7512         if (cl.csqc_vidvars.drawworld)
7513         {
7514                 if (cl_decals_newsystem.integer)
7515                 {
7516                         R_DrawModelDecals();
7517                         if (r_timereport_active)
7518                                 R_TimeReport("modeldecals");
7519                 }
7520                 else
7521                 {
7522                         R_DrawDecals();
7523                         if (r_timereport_active)
7524                                 R_TimeReport("decals");
7525                 }
7526
7527                 R_DrawParticles();
7528                 if (r_timereport_active)
7529                         R_TimeReport("particles");
7530
7531                 R_DrawExplosions();
7532                 if (r_timereport_active)
7533                         R_TimeReport("explosions");
7534
7535                 R_DrawLightningBeams();
7536                 if (r_timereport_active)
7537                         R_TimeReport("lightning");
7538         }
7539
7540         if (cl.csqc_loaded)
7541                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7542
7543         if (r_refdef.view.showdebug)
7544         {
7545                 if (cl_locs_show.integer)
7546                 {
7547                         R_DrawLocs();
7548                         if (r_timereport_active)
7549                                 R_TimeReport("showlocs");
7550                 }
7551
7552                 if (r_drawportals.integer)
7553                 {
7554                         R_DrawPortals();
7555                         if (r_timereport_active)
7556                                 R_TimeReport("portals");
7557                 }
7558
7559                 if (r_showbboxes.value > 0)
7560                 {
7561                         R_DrawEntityBBoxes();
7562                         if (r_timereport_active)
7563                                 R_TimeReport("bboxes");
7564                 }
7565         }
7566
7567         if (r_transparent.integer)
7568         {
7569                 R_MeshQueue_RenderTransparent();
7570                 if (r_timereport_active)
7571                         R_TimeReport("drawtrans");
7572         }
7573
7574         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))
7575         {
7576                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7577                 if (r_timereport_active)
7578                         R_TimeReport("worlddebug");
7579                 R_DrawModelsDebug();
7580                 if (r_timereport_active)
7581                         R_TimeReport("modeldebug");
7582         }
7583
7584         if (cl.csqc_vidvars.drawworld)
7585         {
7586                 R_Shadow_DrawCoronas();
7587                 if (r_timereport_active)
7588                         R_TimeReport("coronas");
7589         }
7590
7591 #if 0
7592         {
7593                 GL_DepthTest(false);
7594                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7595                 GL_Color(1, 1, 1, 1);
7596                 qglBegin(GL_POLYGON);
7597                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7598                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7599                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7600                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7601                 qglEnd();
7602                 qglBegin(GL_POLYGON);
7603                 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]);
7604                 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]);
7605                 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]);
7606                 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]);
7607                 qglEnd();
7608                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7609         }
7610 #endif
7611
7612         // don't let sound skip if going slow
7613         if (r_refdef.scene.extraupdate)
7614                 S_ExtraUpdate ();
7615 }
7616
7617 static const unsigned short bboxelements[36] =
7618 {
7619         5, 1, 3, 5, 3, 7,
7620         6, 2, 0, 6, 0, 4,
7621         7, 3, 2, 7, 2, 6,
7622         4, 0, 1, 4, 1, 5,
7623         4, 5, 7, 4, 7, 6,
7624         1, 0, 2, 1, 2, 3,
7625 };
7626
7627 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7628 {
7629         int i;
7630         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7631
7632         RSurf_ActiveWorldEntity();
7633
7634         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7635         GL_DepthMask(false);
7636         GL_DepthRange(0, 1);
7637         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7638 //      R_Mesh_ResetTextureState();
7639
7640         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7641         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7642         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7643         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7644         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7645         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7646         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7647         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7648         R_FillColors(color4f, 8, cr, cg, cb, ca);
7649         if (r_refdef.fogenabled)
7650         {
7651                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7652                 {
7653                         f1 = RSurf_FogVertex(v);
7654                         f2 = 1 - f1;
7655                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7656                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7657                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7658                 }
7659         }
7660         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7661         R_Mesh_ResetTextureState();
7662         R_SetupShader_Generic_NoTexture(false, false);
7663         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7664 }
7665
7666 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7667 {
7668         prvm_prog_t *prog = SVVM_prog;
7669         int i;
7670         float color[4];
7671         prvm_edict_t *edict;
7672
7673         // this function draws bounding boxes of server entities
7674         if (!sv.active)
7675                 return;
7676
7677         GL_CullFace(GL_NONE);
7678         R_SetupShader_Generic_NoTexture(false, false);
7679
7680         for (i = 0;i < numsurfaces;i++)
7681         {
7682                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7683                 switch ((int)PRVM_serveredictfloat(edict, solid))
7684                 {
7685                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7686                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7687                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7688                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7689                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7690                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7691                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7692                 }
7693                 color[3] *= r_showbboxes.value;
7694                 color[3] = bound(0, color[3], 1);
7695                 GL_DepthTest(!r_showdisabledepthtest.integer);
7696                 GL_CullFace(r_refdef.view.cullface_front);
7697                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7698         }
7699 }
7700
7701 static void R_DrawEntityBBoxes(void)
7702 {
7703         int i;
7704         prvm_edict_t *edict;
7705         vec3_t center;
7706         prvm_prog_t *prog = SVVM_prog;
7707
7708         // this function draws bounding boxes of server entities
7709         if (!sv.active)
7710                 return;
7711
7712         for (i = 0;i < prog->num_edicts;i++)
7713         {
7714                 edict = PRVM_EDICT_NUM(i);
7715                 if (edict->priv.server->free)
7716                         continue;
7717                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7718                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7719                         continue;
7720                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7721                         continue;
7722                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7723                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7724         }
7725 }
7726
7727 static const int nomodelelement3i[24] =
7728 {
7729         5, 2, 0,
7730         5, 1, 2,
7731         5, 0, 3,
7732         5, 3, 1,
7733         0, 2, 4,
7734         2, 1, 4,
7735         3, 0, 4,
7736         1, 3, 4
7737 };
7738
7739 static const unsigned short nomodelelement3s[24] =
7740 {
7741         5, 2, 0,
7742         5, 1, 2,
7743         5, 0, 3,
7744         5, 3, 1,
7745         0, 2, 4,
7746         2, 1, 4,
7747         3, 0, 4,
7748         1, 3, 4
7749 };
7750
7751 static const float nomodelvertex3f[6*3] =
7752 {
7753         -16,   0,   0,
7754          16,   0,   0,
7755           0, -16,   0,
7756           0,  16,   0,
7757           0,   0, -16,
7758           0,   0,  16
7759 };
7760
7761 static const float nomodelcolor4f[6*4] =
7762 {
7763         0.0f, 0.0f, 0.5f, 1.0f,
7764         0.0f, 0.0f, 0.5f, 1.0f,
7765         0.0f, 0.5f, 0.0f, 1.0f,
7766         0.0f, 0.5f, 0.0f, 1.0f,
7767         0.5f, 0.0f, 0.0f, 1.0f,
7768         0.5f, 0.0f, 0.0f, 1.0f
7769 };
7770
7771 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7772 {
7773         int i;
7774         float f1, f2, *c;
7775         float color4f[6*4];
7776
7777         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);
7778
7779         // this is only called once per entity so numsurfaces is always 1, and
7780         // surfacelist is always {0}, so this code does not handle batches
7781
7782         if (rsurface.ent_flags & RENDER_ADDITIVE)
7783         {
7784                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7785                 GL_DepthMask(false);
7786         }
7787         else if (rsurface.colormod[3] < 1)
7788         {
7789                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7790                 GL_DepthMask(false);
7791         }
7792         else
7793         {
7794                 GL_BlendFunc(GL_ONE, GL_ZERO);
7795                 GL_DepthMask(true);
7796         }
7797         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7798         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7799         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7800         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7801         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7802         for (i = 0, c = color4f;i < 6;i++, c += 4)
7803         {
7804                 c[0] *= rsurface.colormod[0];
7805                 c[1] *= rsurface.colormod[1];
7806                 c[2] *= rsurface.colormod[2];
7807                 c[3] *= rsurface.colormod[3];
7808         }
7809         if (r_refdef.fogenabled)
7810         {
7811                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7812                 {
7813                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7814                         f2 = 1 - f1;
7815                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7816                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7817                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7818                 }
7819         }
7820 //      R_Mesh_ResetTextureState();
7821         R_SetupShader_Generic_NoTexture(false, false);
7822         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7823         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7824 }
7825
7826 void R_DrawNoModel(entity_render_t *ent)
7827 {
7828         vec3_t org;
7829         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7830         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7831                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7832         else
7833                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7834 }
7835
7836 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7837 {
7838         vec3_t right1, right2, diff, normal;
7839
7840         VectorSubtract (org2, org1, normal);
7841
7842         // calculate 'right' vector for start
7843         VectorSubtract (r_refdef.view.origin, org1, diff);
7844         CrossProduct (normal, diff, right1);
7845         VectorNormalize (right1);
7846
7847         // calculate 'right' vector for end
7848         VectorSubtract (r_refdef.view.origin, org2, diff);
7849         CrossProduct (normal, diff, right2);
7850         VectorNormalize (right2);
7851
7852         vert[ 0] = org1[0] + width * right1[0];
7853         vert[ 1] = org1[1] + width * right1[1];
7854         vert[ 2] = org1[2] + width * right1[2];
7855         vert[ 3] = org1[0] - width * right1[0];
7856         vert[ 4] = org1[1] - width * right1[1];
7857         vert[ 5] = org1[2] - width * right1[2];
7858         vert[ 6] = org2[0] - width * right2[0];
7859         vert[ 7] = org2[1] - width * right2[1];
7860         vert[ 8] = org2[2] - width * right2[2];
7861         vert[ 9] = org2[0] + width * right2[0];
7862         vert[10] = org2[1] + width * right2[1];
7863         vert[11] = org2[2] + width * right2[2];
7864 }
7865
7866 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)
7867 {
7868         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7869         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7870         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7871         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7872         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7873         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7874         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7875         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7876         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7877         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7878         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7879         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7880 }
7881
7882 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7883 {
7884         int i;
7885         float *vertex3f;
7886         float v[3];
7887         VectorSet(v, x, y, z);
7888         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7889                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7890                         break;
7891         if (i == mesh->numvertices)
7892         {
7893                 if (mesh->numvertices < mesh->maxvertices)
7894                 {
7895                         VectorCopy(v, vertex3f);
7896                         mesh->numvertices++;
7897                 }
7898                 return mesh->numvertices;
7899         }
7900         else
7901                 return i;
7902 }
7903
7904 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7905 {
7906         int i;
7907         int *e, element[3];
7908         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7909         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7910         e = mesh->element3i + mesh->numtriangles * 3;
7911         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7912         {
7913                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7914                 if (mesh->numtriangles < mesh->maxtriangles)
7915                 {
7916                         *e++ = element[0];
7917                         *e++ = element[1];
7918                         *e++ = element[2];
7919                         mesh->numtriangles++;
7920                 }
7921                 element[1] = element[2];
7922         }
7923 }
7924
7925 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7926 {
7927         int i;
7928         int *e, element[3];
7929         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7930         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7931         e = mesh->element3i + mesh->numtriangles * 3;
7932         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7933         {
7934                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7935                 if (mesh->numtriangles < mesh->maxtriangles)
7936                 {
7937                         *e++ = element[0];
7938                         *e++ = element[1];
7939                         *e++ = element[2];
7940                         mesh->numtriangles++;
7941                 }
7942                 element[1] = element[2];
7943         }
7944 }
7945
7946 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7947 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7948 {
7949         int planenum, planenum2;
7950         int w;
7951         int tempnumpoints;
7952         mplane_t *plane, *plane2;
7953         double maxdist;
7954         double temppoints[2][256*3];
7955         // figure out how large a bounding box we need to properly compute this brush
7956         maxdist = 0;
7957         for (w = 0;w < numplanes;w++)
7958                 maxdist = max(maxdist, fabs(planes[w].dist));
7959         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7960         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7961         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7962         {
7963                 w = 0;
7964                 tempnumpoints = 4;
7965                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7966                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7967                 {
7968                         if (planenum2 == planenum)
7969                                 continue;
7970                         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);
7971                         w = !w;
7972                 }
7973                 if (tempnumpoints < 3)
7974                         continue;
7975                 // generate elements forming a triangle fan for this polygon
7976                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7977         }
7978 }
7979
7980 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)
7981 {
7982         texturelayer_t *layer;
7983         layer = t->currentlayers + t->currentnumlayers++;
7984         layer->type = type;
7985         layer->depthmask = depthmask;
7986         layer->blendfunc1 = blendfunc1;
7987         layer->blendfunc2 = blendfunc2;
7988         layer->texture = texture;
7989         layer->texmatrix = *matrix;
7990         layer->color[0] = r;
7991         layer->color[1] = g;
7992         layer->color[2] = b;
7993         layer->color[3] = a;
7994 }
7995
7996 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7997 {
7998         if(parms[0] == 0 && parms[1] == 0)
7999                 return false;
8000         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8001                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
8002                         return false;
8003         return true;
8004 }
8005
8006 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
8007 {
8008         double index, f;
8009         index = parms[2] + rsurface.shadertime * parms[3];
8010         index -= floor(index);
8011         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
8012         {
8013         default:
8014         case Q3WAVEFUNC_NONE:
8015         case Q3WAVEFUNC_NOISE:
8016         case Q3WAVEFUNC_COUNT:
8017                 f = 0;
8018                 break;
8019         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
8020         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
8021         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
8022         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
8023         case Q3WAVEFUNC_TRIANGLE:
8024                 index *= 4;
8025                 f = index - floor(index);
8026                 if (index < 1)
8027                 {
8028                         // f = f;
8029                 }
8030                 else if (index < 2)
8031                         f = 1 - f;
8032                 else if (index < 3)
8033                         f = -f;
8034                 else
8035                         f = -(1 - f);
8036                 break;
8037         }
8038         f = parms[0] + parms[1] * f;
8039         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8040                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8041         return (float) f;
8042 }
8043
8044 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8045 {
8046         int w, h, idx;
8047         float shadertime;
8048         float f;
8049         float offsetd[2];
8050         float tcmat[12];
8051         matrix4x4_t matrix, temp;
8052         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8053         // it's better to have one huge fixup every 9 hours than gradual
8054         // degradation over time which looks consistently bad after many hours.
8055         //
8056         // tcmod scroll in particular suffers from this degradation which can't be
8057         // effectively worked around even with floor() tricks because we don't
8058         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8059         // a workaround involving floor() would be incorrect anyway...
8060         shadertime = rsurface.shadertime;
8061         if (shadertime >= 32768.0f)
8062                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8063         switch(tcmod->tcmod)
8064         {
8065                 case Q3TCMOD_COUNT:
8066                 case Q3TCMOD_NONE:
8067                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8068                                 matrix = r_waterscrollmatrix;
8069                         else
8070                                 matrix = identitymatrix;
8071                         break;
8072                 case Q3TCMOD_ENTITYTRANSLATE:
8073                         // this is used in Q3 to allow the gamecode to control texcoord
8074                         // scrolling on the entity, which is not supported in darkplaces yet.
8075                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8076                         break;
8077                 case Q3TCMOD_ROTATE:
8078                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8079                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8080                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8081                         break;
8082                 case Q3TCMOD_SCALE:
8083                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8084                         break;
8085                 case Q3TCMOD_SCROLL:
8086                         // this particular tcmod is a "bug for bug" compatible one with regards to
8087                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8088                         // specifically did the wrapping and so we must mimic that...
8089                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8090                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8091                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8092                         break;
8093                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8094                         w = (int) tcmod->parms[0];
8095                         h = (int) tcmod->parms[1];
8096                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8097                         f = f - floor(f);
8098                         idx = (int) floor(f * w * h);
8099                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8100                         break;
8101                 case Q3TCMOD_STRETCH:
8102                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8103                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8104                         break;
8105                 case Q3TCMOD_TRANSFORM:
8106                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8107                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8108                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8109                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8110                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8111                         break;
8112                 case Q3TCMOD_TURBULENT:
8113                         // this is handled in the RSurf_PrepareVertices function
8114                         matrix = identitymatrix;
8115                         break;
8116         }
8117         temp = *texmatrix;
8118         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8119 }
8120
8121 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8122 {
8123         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8124         char name[MAX_QPATH];
8125         skinframe_t *skinframe;
8126         unsigned char pixels[296*194];
8127         strlcpy(cache->name, skinname, sizeof(cache->name));
8128         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8129         if (developer_loading.integer)
8130                 Con_Printf("loading %s\n", name);
8131         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8132         if (!skinframe || !skinframe->base)
8133         {
8134                 unsigned char *f;
8135                 fs_offset_t filesize;
8136                 skinframe = NULL;
8137                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8138                 if (f)
8139                 {
8140                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8141                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8142                         Mem_Free(f);
8143                 }
8144         }
8145         cache->skinframe = skinframe;
8146 }
8147
8148 texture_t *R_GetCurrentTexture(texture_t *t)
8149 {
8150         int i;
8151         const entity_render_t *ent = rsurface.entity;
8152         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8153         q3shaderinfo_layer_tcmod_t *tcmod;
8154
8155         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8156                 return t->currentframe;
8157         t->update_lastrenderframe = r_textureframe;
8158         t->update_lastrenderentity = (void *)ent;
8159
8160         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8161                 t->camera_entity = ent->entitynumber;
8162         else
8163                 t->camera_entity = 0;
8164
8165         // switch to an alternate material if this is a q1bsp animated material
8166         {
8167                 texture_t *texture = t;
8168                 int s = rsurface.ent_skinnum;
8169                 if ((unsigned int)s >= (unsigned int)model->numskins)
8170                         s = 0;
8171                 if (model->skinscenes)
8172                 {
8173                         if (model->skinscenes[s].framecount > 1)
8174                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8175                         else
8176                                 s = model->skinscenes[s].firstframe;
8177                 }
8178                 if (s > 0)
8179                         t = t + s * model->num_surfaces;
8180                 if (t->animated)
8181                 {
8182                         // use an alternate animation if the entity's frame is not 0,
8183                         // and only if the texture has an alternate animation
8184                         if (t->animated == 2) // q2bsp
8185                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8186                         else if (rsurface.ent_alttextures && t->anim_total[1])
8187                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8188                         else
8189                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8190                 }
8191                 texture->currentframe = t;
8192         }
8193
8194         // update currentskinframe to be a qw skin or animation frame
8195         if (rsurface.ent_qwskin >= 0)
8196         {
8197                 i = rsurface.ent_qwskin;
8198                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8199                 {
8200                         r_qwskincache_size = cl.maxclients;
8201                         if (r_qwskincache)
8202                                 Mem_Free(r_qwskincache);
8203                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8204                 }
8205                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8206                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8207                 t->currentskinframe = r_qwskincache[i].skinframe;
8208                 if (t->currentskinframe == NULL)
8209                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8210         }
8211         else if (t->numskinframes >= 2)
8212                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8213         if (t->backgroundnumskinframes >= 2)
8214                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8215
8216         t->currentmaterialflags = t->basematerialflags;
8217         t->currentalpha = rsurface.colormod[3] * t->basealpha;
8218         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8219                 t->currentalpha *= r_wateralpha.value;
8220         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8221                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8222         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8223                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8224         if (!(rsurface.ent_flags & RENDER_LIGHT))
8225                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8226         else if (FAKELIGHT_ENABLED)
8227         {
8228                 // no modellight if using fakelight for the map
8229         }
8230         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8231         {
8232                 // pick a model lighting mode
8233                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8234                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8235                 else
8236                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8237         }
8238         if (rsurface.ent_flags & RENDER_ADDITIVE)
8239                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8240         else if (t->currentalpha < 1)
8241                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8242         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8243         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8244                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8245         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8246                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8247         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8248                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8249         if (t->backgroundnumskinframes)
8250                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8251         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8252         {
8253                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8254                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8255         }
8256         else
8257                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8258         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8259         {
8260                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8261                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8262         }
8263         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8264                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8265
8266         // there is no tcmod
8267         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8268         {
8269                 t->currenttexmatrix = r_waterscrollmatrix;
8270                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8271         }
8272         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8273         {
8274                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8275                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8276         }
8277
8278         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8279                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8280         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8281                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8282
8283         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8284         if (t->currentskinframe->qpixels)
8285                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8286         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8287         if (!t->basetexture)
8288                 t->basetexture = r_texture_notexture;
8289         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8290         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8291         t->nmaptexture = t->currentskinframe->nmap;
8292         if (!t->nmaptexture)
8293                 t->nmaptexture = r_texture_blanknormalmap;
8294         t->glosstexture = r_texture_black;
8295         t->glowtexture = t->currentskinframe->glow;
8296         t->fogtexture = t->currentskinframe->fog;
8297         t->reflectmasktexture = t->currentskinframe->reflect;
8298         if (t->backgroundnumskinframes)
8299         {
8300                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8301                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8302                 t->backgroundglosstexture = r_texture_black;
8303                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8304                 if (!t->backgroundnmaptexture)
8305                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8306                 // make sure that if glow is going to be used, both textures are not NULL
8307                 if (!t->backgroundglowtexture && t->glowtexture)
8308                         t->backgroundglowtexture = r_texture_black;
8309                 if (!t->glowtexture && t->backgroundglowtexture)
8310                         t->glowtexture = r_texture_black;
8311         }
8312         else
8313         {
8314                 t->backgroundbasetexture = r_texture_white;
8315                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8316                 t->backgroundglosstexture = r_texture_black;
8317                 t->backgroundglowtexture = NULL;
8318         }
8319         t->specularpower = r_shadow_glossexponent.value;
8320         // TODO: store reference values for these in the texture?
8321         t->specularscale = 0;
8322         if (r_shadow_gloss.integer > 0)
8323         {
8324                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8325                 {
8326                         if (r_shadow_glossintensity.value > 0)
8327                         {
8328                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8329                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8330                                 t->specularscale = r_shadow_glossintensity.value;
8331                         }
8332                 }
8333                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8334                 {
8335                         t->glosstexture = r_texture_white;
8336                         t->backgroundglosstexture = r_texture_white;
8337                         t->specularscale = r_shadow_gloss2intensity.value;
8338                         t->specularpower = r_shadow_gloss2exponent.value;
8339                 }
8340         }
8341         t->specularscale *= t->specularscalemod;
8342         t->specularpower *= t->specularpowermod;
8343         t->rtlightambient = 0;
8344
8345         // lightmaps mode looks bad with dlights using actual texturing, so turn
8346         // off the colormap and glossmap, but leave the normalmap on as it still
8347         // accurately represents the shading involved
8348         if (gl_lightmaps.integer)
8349         {
8350                 t->basetexture = r_texture_grey128;
8351                 t->pantstexture = r_texture_black;
8352                 t->shirttexture = r_texture_black;
8353                 if (gl_lightmaps.integer < 2)
8354                         t->nmaptexture = r_texture_blanknormalmap;
8355                 t->glosstexture = r_texture_black;
8356                 t->glowtexture = NULL;
8357                 t->fogtexture = NULL;
8358                 t->reflectmasktexture = NULL;
8359                 t->backgroundbasetexture = NULL;
8360                 if (gl_lightmaps.integer < 2)
8361                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8362                 t->backgroundglosstexture = r_texture_black;
8363                 t->backgroundglowtexture = NULL;
8364                 t->specularscale = 0;
8365                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8366         }
8367
8368         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8369         VectorClear(t->dlightcolor);
8370         t->currentnumlayers = 0;
8371         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8372         {
8373                 int blendfunc1, blendfunc2;
8374                 qboolean depthmask;
8375                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8376                 {
8377                         blendfunc1 = GL_SRC_ALPHA;
8378                         blendfunc2 = GL_ONE;
8379                 }
8380                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8381                 {
8382                         blendfunc1 = GL_SRC_ALPHA;
8383                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8384                 }
8385                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8386                 {
8387                         blendfunc1 = t->customblendfunc[0];
8388                         blendfunc2 = t->customblendfunc[1];
8389                 }
8390                 else
8391                 {
8392                         blendfunc1 = GL_ONE;
8393                         blendfunc2 = GL_ZERO;
8394                 }
8395                 // don't colormod evilblend textures
8396                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8397                         VectorSet(t->lightmapcolor, 1, 1, 1);
8398                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8399                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8400                 {
8401                         // fullbright is not affected by r_refdef.lightmapintensity
8402                         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]);
8403                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8404                                 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]);
8405                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8406                                 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]);
8407                 }
8408                 else
8409                 {
8410                         vec3_t ambientcolor;
8411                         float colorscale;
8412                         // set the color tint used for lights affecting this surface
8413                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8414                         colorscale = 2;
8415                         // q3bsp has no lightmap updates, so the lightstylevalue that
8416                         // would normally be baked into the lightmap must be
8417                         // applied to the color
8418                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8419                         if (model->type == mod_brushq3)
8420                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8421                         colorscale *= r_refdef.lightmapintensity;
8422                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8423                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8424                         // basic lit geometry
8425                         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]);
8426                         // add pants/shirt if needed
8427                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8428                                 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]);
8429                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8430                                 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]);
8431                         // now add ambient passes if needed
8432                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8433                         {
8434                                 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]);
8435                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8436                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->pantstexture, &t->currenttexmatrix, rsurface.colormap_pantscolor[0] * ambientcolor[0], rsurface.colormap_pantscolor[1] * ambientcolor[1], rsurface.colormap_pantscolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8437                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8438                                         R_Texture_AddLayer(t, false, GL_SRC_ALPHA, GL_ONE, TEXTURELAYERTYPE_TEXTURE, t->shirttexture, &t->currenttexmatrix, rsurface.colormap_shirtcolor[0] * ambientcolor[0], rsurface.colormap_shirtcolor[1] * ambientcolor[1], rsurface.colormap_shirtcolor[2] * ambientcolor[2], t->lightmapcolor[3]);
8439                         }
8440                 }
8441                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8442                         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]);
8443                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8444                 {
8445                         // if this is opaque use alpha blend which will darken the earlier
8446                         // passes cheaply.
8447                         //
8448                         // if this is an alpha blended material, all the earlier passes
8449                         // were darkened by fog already, so we only need to add the fog
8450                         // color ontop through the fog mask texture
8451                         //
8452                         // if this is an additive blended material, all the earlier passes
8453                         // were darkened by fog already, and we should not add fog color
8454                         // (because the background was not darkened, there is no fog color
8455                         // that was lost behind it).
8456                         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]);
8457                 }
8458         }
8459
8460         return t;
8461 }
8462
8463 rsurfacestate_t rsurface;
8464
8465 void RSurf_ActiveWorldEntity(void)
8466 {
8467         dp_model_t *model = r_refdef.scene.worldmodel;
8468         //if (rsurface.entity == r_refdef.scene.worldentity)
8469         //      return;
8470         rsurface.entity = r_refdef.scene.worldentity;
8471         rsurface.skeleton = NULL;
8472         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8473         rsurface.ent_skinnum = 0;
8474         rsurface.ent_qwskin = -1;
8475         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8476         rsurface.shadertime = r_refdef.scene.time;
8477         rsurface.matrix = identitymatrix;
8478         rsurface.inversematrix = identitymatrix;
8479         rsurface.matrixscale = 1;
8480         rsurface.inversematrixscale = 1;
8481         R_EntityMatrix(&identitymatrix);
8482         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8483         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8484         rsurface.fograngerecip = r_refdef.fograngerecip;
8485         rsurface.fogheightfade = r_refdef.fogheightfade;
8486         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8487         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8488         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8489         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8490         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8491         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8492         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8493         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8494         rsurface.colormod[3] = 1;
8495         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);
8496         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8497         rsurface.frameblend[0].lerp = 1;
8498         rsurface.ent_alttextures = false;
8499         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8500         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8501         rsurface.entityskeletaltransform3x4 = NULL;
8502         rsurface.entityskeletaltransform3x4buffer = NULL;
8503         rsurface.entityskeletaltransform3x4offset = 0;
8504         rsurface.entityskeletaltransform3x4size = 0;;
8505         rsurface.entityskeletalnumtransforms = 0;
8506         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8507         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8508         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8509         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8510         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8511         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8512         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8513         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8514         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8515         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8516         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8517         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8518         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8519         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8520         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8521         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8522         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8523         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8524         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8525         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8526         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8527         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8528         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8529         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8530         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8531         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8532         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8533         rsurface.modelelement3i = model->surfmesh.data_element3i;
8534         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8535         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8536         rsurface.modelelement3s = model->surfmesh.data_element3s;
8537         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8538         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8539         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8540         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8541         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8542         rsurface.modelsurfaces = model->data_surfaces;
8543         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8544         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8545         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8546         rsurface.modelgeneratedvertex = false;
8547         rsurface.batchgeneratedvertex = false;
8548         rsurface.batchfirstvertex = 0;
8549         rsurface.batchnumvertices = 0;
8550         rsurface.batchfirsttriangle = 0;
8551         rsurface.batchnumtriangles = 0;
8552         rsurface.batchvertex3f  = NULL;
8553         rsurface.batchvertex3f_vertexbuffer = NULL;
8554         rsurface.batchvertex3f_bufferoffset = 0;
8555         rsurface.batchsvector3f = NULL;
8556         rsurface.batchsvector3f_vertexbuffer = NULL;
8557         rsurface.batchsvector3f_bufferoffset = 0;
8558         rsurface.batchtvector3f = NULL;
8559         rsurface.batchtvector3f_vertexbuffer = NULL;
8560         rsurface.batchtvector3f_bufferoffset = 0;
8561         rsurface.batchnormal3f  = NULL;
8562         rsurface.batchnormal3f_vertexbuffer = NULL;
8563         rsurface.batchnormal3f_bufferoffset = 0;
8564         rsurface.batchlightmapcolor4f = NULL;
8565         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8566         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8567         rsurface.batchtexcoordtexture2f = NULL;
8568         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8569         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8570         rsurface.batchtexcoordlightmap2f = NULL;
8571         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8572         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8573         rsurface.batchskeletalindex4ub = NULL;
8574         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8575         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8576         rsurface.batchskeletalweight4ub = NULL;
8577         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8578         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8579         rsurface.batchvertexmesh = NULL;
8580         rsurface.batchvertexmesh_vertexbuffer = NULL;
8581         rsurface.batchvertexmesh_bufferoffset = 0;
8582         rsurface.batchelement3i = NULL;
8583         rsurface.batchelement3i_indexbuffer = NULL;
8584         rsurface.batchelement3i_bufferoffset = 0;
8585         rsurface.batchelement3s = NULL;
8586         rsurface.batchelement3s_indexbuffer = NULL;
8587         rsurface.batchelement3s_bufferoffset = 0;
8588         rsurface.passcolor4f = NULL;
8589         rsurface.passcolor4f_vertexbuffer = NULL;
8590         rsurface.passcolor4f_bufferoffset = 0;
8591         rsurface.forcecurrenttextureupdate = false;
8592 }
8593
8594 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8595 {
8596         dp_model_t *model = ent->model;
8597         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8598         //      return;
8599         rsurface.entity = (entity_render_t *)ent;
8600         rsurface.skeleton = ent->skeleton;
8601         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8602         rsurface.ent_skinnum = ent->skinnum;
8603         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;
8604         rsurface.ent_flags = ent->flags;
8605         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8606         rsurface.matrix = ent->matrix;
8607         rsurface.inversematrix = ent->inversematrix;
8608         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8609         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8610         R_EntityMatrix(&rsurface.matrix);
8611         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8612         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8613         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8614         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8615         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8616         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8617         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8618         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8619         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8620         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8621         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8622         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8623         rsurface.colormod[3] = ent->alpha;
8624         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8625         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8626         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8627         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8628         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8629         if (ent->model->brush.submodel && !prepass)
8630         {
8631                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8632                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8633         }
8634         // if the animcache code decided it should use the shader path, skip the deform step
8635         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8636         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8637         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8638         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8639         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8640         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8641         {
8642                 if (ent->animcache_vertex3f)
8643                 {
8644                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8645                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8646                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8647                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8648                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8649                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8650                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8651                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8652                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8653                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8654                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8655                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8656                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8657                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8658                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8659                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8660                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8661                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8662                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8663                 }
8664                 else if (wanttangents)
8665                 {
8666                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8667                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8668                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8669                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8670                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8671                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8672                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8673                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8674                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8675                         rsurface.modelvertexmesh = NULL;
8676                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8677                         rsurface.modelvertexmesh_bufferoffset = 0;
8678                         rsurface.modelvertex3f_vertexbuffer = NULL;
8679                         rsurface.modelvertex3f_bufferoffset = 0;
8680                         rsurface.modelvertex3f_vertexbuffer = 0;
8681                         rsurface.modelvertex3f_bufferoffset = 0;
8682                         rsurface.modelsvector3f_vertexbuffer = 0;
8683                         rsurface.modelsvector3f_bufferoffset = 0;
8684                         rsurface.modeltvector3f_vertexbuffer = 0;
8685                         rsurface.modeltvector3f_bufferoffset = 0;
8686                         rsurface.modelnormal3f_vertexbuffer = 0;
8687                         rsurface.modelnormal3f_bufferoffset = 0;
8688                 }
8689                 else if (wantnormals)
8690                 {
8691                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8692                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8693                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8694                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8695                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8696                         rsurface.modelsvector3f = NULL;
8697                         rsurface.modeltvector3f = NULL;
8698                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8699                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8700                         rsurface.modelvertexmesh = NULL;
8701                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8702                         rsurface.modelvertexmesh_bufferoffset = 0;
8703                         rsurface.modelvertex3f_vertexbuffer = NULL;
8704                         rsurface.modelvertex3f_bufferoffset = 0;
8705                         rsurface.modelvertex3f_vertexbuffer = 0;
8706                         rsurface.modelvertex3f_bufferoffset = 0;
8707                         rsurface.modelsvector3f_vertexbuffer = 0;
8708                         rsurface.modelsvector3f_bufferoffset = 0;
8709                         rsurface.modeltvector3f_vertexbuffer = 0;
8710                         rsurface.modeltvector3f_bufferoffset = 0;
8711                         rsurface.modelnormal3f_vertexbuffer = 0;
8712                         rsurface.modelnormal3f_bufferoffset = 0;
8713                 }
8714                 else
8715                 {
8716                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8717                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8718                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8719                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8720                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8721                         rsurface.modelsvector3f = NULL;
8722                         rsurface.modeltvector3f = NULL;
8723                         rsurface.modelnormal3f = NULL;
8724                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8725                         rsurface.modelvertexmesh = NULL;
8726                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8727                         rsurface.modelvertexmesh_bufferoffset = 0;
8728                         rsurface.modelvertex3f_vertexbuffer = NULL;
8729                         rsurface.modelvertex3f_bufferoffset = 0;
8730                         rsurface.modelvertex3f_vertexbuffer = 0;
8731                         rsurface.modelvertex3f_bufferoffset = 0;
8732                         rsurface.modelsvector3f_vertexbuffer = 0;
8733                         rsurface.modelsvector3f_bufferoffset = 0;
8734                         rsurface.modeltvector3f_vertexbuffer = 0;
8735                         rsurface.modeltvector3f_bufferoffset = 0;
8736                         rsurface.modelnormal3f_vertexbuffer = 0;
8737                         rsurface.modelnormal3f_bufferoffset = 0;
8738                 }
8739                 rsurface.modelgeneratedvertex = true;
8740         }
8741         else
8742         {
8743                 if (rsurface.entityskeletaltransform3x4)
8744                 {
8745                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8746                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8747                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8748                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8749                 }
8750                 else
8751                 {
8752                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8753                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8754                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8755                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8756                 }
8757                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8758                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8759                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8760                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8761                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8762                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8763                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8764                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8765                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8766                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8767                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8768                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8769                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8770                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8771                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8772                 rsurface.modelgeneratedvertex = false;
8773         }
8774         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8775         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8776         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8777         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8778         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8779         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8780         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8781         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8782         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8783         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8784         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8785         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8786         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8787         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8788         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8789         rsurface.modelelement3i = model->surfmesh.data_element3i;
8790         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8791         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8792         rsurface.modelelement3s = model->surfmesh.data_element3s;
8793         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8794         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8795         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8796         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8797         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8798         rsurface.modelsurfaces = model->data_surfaces;
8799         rsurface.batchgeneratedvertex = false;
8800         rsurface.batchfirstvertex = 0;
8801         rsurface.batchnumvertices = 0;
8802         rsurface.batchfirsttriangle = 0;
8803         rsurface.batchnumtriangles = 0;
8804         rsurface.batchvertex3f  = NULL;
8805         rsurface.batchvertex3f_vertexbuffer = NULL;
8806         rsurface.batchvertex3f_bufferoffset = 0;
8807         rsurface.batchsvector3f = NULL;
8808         rsurface.batchsvector3f_vertexbuffer = NULL;
8809         rsurface.batchsvector3f_bufferoffset = 0;
8810         rsurface.batchtvector3f = NULL;
8811         rsurface.batchtvector3f_vertexbuffer = NULL;
8812         rsurface.batchtvector3f_bufferoffset = 0;
8813         rsurface.batchnormal3f  = NULL;
8814         rsurface.batchnormal3f_vertexbuffer = NULL;
8815         rsurface.batchnormal3f_bufferoffset = 0;
8816         rsurface.batchlightmapcolor4f = NULL;
8817         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8818         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8819         rsurface.batchtexcoordtexture2f = NULL;
8820         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8821         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8822         rsurface.batchtexcoordlightmap2f = NULL;
8823         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8824         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8825         rsurface.batchskeletalindex4ub = NULL;
8826         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8827         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8828         rsurface.batchskeletalweight4ub = NULL;
8829         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8830         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8831         rsurface.batchvertexmesh = NULL;
8832         rsurface.batchvertexmesh_vertexbuffer = NULL;
8833         rsurface.batchvertexmesh_bufferoffset = 0;
8834         rsurface.batchelement3i = NULL;
8835         rsurface.batchelement3i_indexbuffer = NULL;
8836         rsurface.batchelement3i_bufferoffset = 0;
8837         rsurface.batchelement3s = NULL;
8838         rsurface.batchelement3s_indexbuffer = NULL;
8839         rsurface.batchelement3s_bufferoffset = 0;
8840         rsurface.passcolor4f = NULL;
8841         rsurface.passcolor4f_vertexbuffer = NULL;
8842         rsurface.passcolor4f_bufferoffset = 0;
8843         rsurface.forcecurrenttextureupdate = false;
8844 }
8845
8846 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)
8847 {
8848         rsurface.entity = r_refdef.scene.worldentity;
8849         rsurface.skeleton = NULL;
8850         rsurface.ent_skinnum = 0;
8851         rsurface.ent_qwskin = -1;
8852         rsurface.ent_flags = entflags;
8853         rsurface.shadertime = r_refdef.scene.time - shadertime;
8854         rsurface.modelnumvertices = numvertices;
8855         rsurface.modelnumtriangles = numtriangles;
8856         rsurface.matrix = *matrix;
8857         rsurface.inversematrix = *inversematrix;
8858         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8859         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8860         R_EntityMatrix(&rsurface.matrix);
8861         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8862         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8863         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8864         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8865         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8866         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8867         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8868         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8869         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8870         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8871         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8872         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8873         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);
8874         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8875         rsurface.frameblend[0].lerp = 1;
8876         rsurface.ent_alttextures = false;
8877         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8878         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8879         rsurface.entityskeletaltransform3x4 = NULL;
8880         rsurface.entityskeletaltransform3x4buffer = NULL;
8881         rsurface.entityskeletaltransform3x4offset = 0;
8882         rsurface.entityskeletaltransform3x4size = 0;
8883         rsurface.entityskeletalnumtransforms = 0;
8884         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8885         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8886         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8887         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8888         if (wanttangents)
8889         {
8890                 rsurface.modelvertex3f = (float *)vertex3f;
8891                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8892                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8893                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8894         }
8895         else if (wantnormals)
8896         {
8897                 rsurface.modelvertex3f = (float *)vertex3f;
8898                 rsurface.modelsvector3f = NULL;
8899                 rsurface.modeltvector3f = NULL;
8900                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8901         }
8902         else
8903         {
8904                 rsurface.modelvertex3f = (float *)vertex3f;
8905                 rsurface.modelsvector3f = NULL;
8906                 rsurface.modeltvector3f = NULL;
8907                 rsurface.modelnormal3f = NULL;
8908         }
8909         rsurface.modelvertexmesh = NULL;
8910         rsurface.modelvertexmesh_vertexbuffer = NULL;
8911         rsurface.modelvertexmesh_bufferoffset = 0;
8912         rsurface.modelvertex3f_vertexbuffer = 0;
8913         rsurface.modelvertex3f_bufferoffset = 0;
8914         rsurface.modelsvector3f_vertexbuffer = 0;
8915         rsurface.modelsvector3f_bufferoffset = 0;
8916         rsurface.modeltvector3f_vertexbuffer = 0;
8917         rsurface.modeltvector3f_bufferoffset = 0;
8918         rsurface.modelnormal3f_vertexbuffer = 0;
8919         rsurface.modelnormal3f_bufferoffset = 0;
8920         rsurface.modelgeneratedvertex = true;
8921         rsurface.modellightmapcolor4f  = (float *)color4f;
8922         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8923         rsurface.modellightmapcolor4f_bufferoffset = 0;
8924         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8925         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8926         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8927         rsurface.modeltexcoordlightmap2f  = NULL;
8928         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8929         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8930         rsurface.modelskeletalindex4ub = NULL;
8931         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8932         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8933         rsurface.modelskeletalweight4ub = NULL;
8934         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8935         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8936         rsurface.modelelement3i = (int *)element3i;
8937         rsurface.modelelement3i_indexbuffer = NULL;
8938         rsurface.modelelement3i_bufferoffset = 0;
8939         rsurface.modelelement3s = (unsigned short *)element3s;
8940         rsurface.modelelement3s_indexbuffer = NULL;
8941         rsurface.modelelement3s_bufferoffset = 0;
8942         rsurface.modellightmapoffsets = NULL;
8943         rsurface.modelsurfaces = NULL;
8944         rsurface.batchgeneratedvertex = false;
8945         rsurface.batchfirstvertex = 0;
8946         rsurface.batchnumvertices = 0;
8947         rsurface.batchfirsttriangle = 0;
8948         rsurface.batchnumtriangles = 0;
8949         rsurface.batchvertex3f  = NULL;
8950         rsurface.batchvertex3f_vertexbuffer = NULL;
8951         rsurface.batchvertex3f_bufferoffset = 0;
8952         rsurface.batchsvector3f = NULL;
8953         rsurface.batchsvector3f_vertexbuffer = NULL;
8954         rsurface.batchsvector3f_bufferoffset = 0;
8955         rsurface.batchtvector3f = NULL;
8956         rsurface.batchtvector3f_vertexbuffer = NULL;
8957         rsurface.batchtvector3f_bufferoffset = 0;
8958         rsurface.batchnormal3f  = NULL;
8959         rsurface.batchnormal3f_vertexbuffer = NULL;
8960         rsurface.batchnormal3f_bufferoffset = 0;
8961         rsurface.batchlightmapcolor4f = NULL;
8962         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8963         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8964         rsurface.batchtexcoordtexture2f = NULL;
8965         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8966         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8967         rsurface.batchtexcoordlightmap2f = NULL;
8968         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8969         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8970         rsurface.batchskeletalindex4ub = NULL;
8971         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8972         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8973         rsurface.batchskeletalweight4ub = NULL;
8974         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8975         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8976         rsurface.batchvertexmesh = NULL;
8977         rsurface.batchvertexmesh_vertexbuffer = NULL;
8978         rsurface.batchvertexmesh_bufferoffset = 0;
8979         rsurface.batchelement3i = NULL;
8980         rsurface.batchelement3i_indexbuffer = NULL;
8981         rsurface.batchelement3i_bufferoffset = 0;
8982         rsurface.batchelement3s = NULL;
8983         rsurface.batchelement3s_indexbuffer = NULL;
8984         rsurface.batchelement3s_bufferoffset = 0;
8985         rsurface.passcolor4f = NULL;
8986         rsurface.passcolor4f_vertexbuffer = NULL;
8987         rsurface.passcolor4f_bufferoffset = 0;
8988         rsurface.forcecurrenttextureupdate = true;
8989
8990         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8991         {
8992                 if ((wantnormals || wanttangents) && !normal3f)
8993                 {
8994                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8995                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8996                 }
8997                 if (wanttangents && !svector3f)
8998                 {
8999                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9000                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
9001                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
9002                 }
9003         }
9004 }
9005
9006 float RSurf_FogPoint(const float *v)
9007 {
9008         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9009         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
9010         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
9011         float FogHeightFade = r_refdef.fogheightfade;
9012         float fogfrac;
9013         unsigned int fogmasktableindex;
9014         if (r_refdef.fogplaneviewabove)
9015                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9016         else
9017                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9018         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
9019         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9020 }
9021
9022 float RSurf_FogVertex(const float *v)
9023 {
9024         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
9025         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9026         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9027         float FogHeightFade = rsurface.fogheightfade;
9028         float fogfrac;
9029         unsigned int fogmasktableindex;
9030         if (r_refdef.fogplaneviewabove)
9031                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9032         else
9033                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9034         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9035         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9036 }
9037
9038 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9039 {
9040         int i;
9041         for (i = 0;i < numelements;i++)
9042                 outelement3i[i] = inelement3i[i] + adjust;
9043 }
9044
9045 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9046 extern cvar_t gl_vbo;
9047 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9048 {
9049         int deformindex;
9050         int firsttriangle;
9051         int numtriangles;
9052         int firstvertex;
9053         int endvertex;
9054         int numvertices;
9055         int surfacefirsttriangle;
9056         int surfacenumtriangles;
9057         int surfacefirstvertex;
9058         int surfaceendvertex;
9059         int surfacenumvertices;
9060         int batchnumsurfaces = texturenumsurfaces;
9061         int batchnumvertices;
9062         int batchnumtriangles;
9063         int needsupdate;
9064         int i, j;
9065         qboolean gaps;
9066         qboolean dynamicvertex;
9067         float amplitude;
9068         float animpos;
9069         float scale;
9070         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9071         float waveparms[4];
9072         unsigned char *ub;
9073         q3shaderinfo_deform_t *deform;
9074         const msurface_t *surface, *firstsurface;
9075         r_vertexmesh_t *vertexmesh;
9076         if (!texturenumsurfaces)
9077                 return;
9078         // find vertex range of this surface batch
9079         gaps = false;
9080         firstsurface = texturesurfacelist[0];
9081         firsttriangle = firstsurface->num_firsttriangle;
9082         batchnumvertices = 0;
9083         batchnumtriangles = 0;
9084         firstvertex = endvertex = firstsurface->num_firstvertex;
9085         for (i = 0;i < texturenumsurfaces;i++)
9086         {
9087                 surface = texturesurfacelist[i];
9088                 if (surface != firstsurface + i)
9089                         gaps = true;
9090                 surfacefirstvertex = surface->num_firstvertex;
9091                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9092                 surfacenumvertices = surface->num_vertices;
9093                 surfacenumtriangles = surface->num_triangles;
9094                 if (firstvertex > surfacefirstvertex)
9095                         firstvertex = surfacefirstvertex;
9096                 if (endvertex < surfaceendvertex)
9097                         endvertex = surfaceendvertex;
9098                 batchnumvertices += surfacenumvertices;
9099                 batchnumtriangles += surfacenumtriangles;
9100         }
9101
9102         r_refdef.stats[r_stat_batch_batches]++;
9103         if (gaps)
9104                 r_refdef.stats[r_stat_batch_withgaps]++;
9105         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9106         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9107         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9108
9109         // we now know the vertex range used, and if there are any gaps in it
9110         rsurface.batchfirstvertex = firstvertex;
9111         rsurface.batchnumvertices = endvertex - firstvertex;
9112         rsurface.batchfirsttriangle = firsttriangle;
9113         rsurface.batchnumtriangles = batchnumtriangles;
9114
9115         // this variable holds flags for which properties have been updated that
9116         // may require regenerating vertexmesh array...
9117         needsupdate = 0;
9118
9119         // check if any dynamic vertex processing must occur
9120         dynamicvertex = false;
9121
9122         // a cvar to force the dynamic vertex path to be taken, for debugging
9123         if (r_batch_debugdynamicvertexpath.integer)
9124         {
9125                 if (!dynamicvertex)
9126                 {
9127                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9128                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9129                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9130                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9131                 }
9132                 dynamicvertex = true;
9133         }
9134
9135         // if there is a chance of animated vertex colors, it's a dynamic batch
9136         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9137         {
9138                 if (!dynamicvertex)
9139                 {
9140                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9141                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9142                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9143                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9144                 }
9145                 dynamicvertex = true;
9146                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9147         }
9148
9149         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9150         {
9151                 switch (deform->deform)
9152                 {
9153                 default:
9154                 case Q3DEFORM_PROJECTIONSHADOW:
9155                 case Q3DEFORM_TEXT0:
9156                 case Q3DEFORM_TEXT1:
9157                 case Q3DEFORM_TEXT2:
9158                 case Q3DEFORM_TEXT3:
9159                 case Q3DEFORM_TEXT4:
9160                 case Q3DEFORM_TEXT5:
9161                 case Q3DEFORM_TEXT6:
9162                 case Q3DEFORM_TEXT7:
9163                 case Q3DEFORM_NONE:
9164                         break;
9165                 case Q3DEFORM_AUTOSPRITE:
9166                         if (!dynamicvertex)
9167                         {
9168                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9169                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9170                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9171                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9172                         }
9173                         dynamicvertex = true;
9174                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9175                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9176                         break;
9177                 case Q3DEFORM_AUTOSPRITE2:
9178                         if (!dynamicvertex)
9179                         {
9180                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9181                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9182                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9183                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9184                         }
9185                         dynamicvertex = true;
9186                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9187                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9188                         break;
9189                 case Q3DEFORM_NORMAL:
9190                         if (!dynamicvertex)
9191                         {
9192                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9193                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9194                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9195                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9196                         }
9197                         dynamicvertex = true;
9198                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9199                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9200                         break;
9201                 case Q3DEFORM_WAVE:
9202                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9203                                 break; // if wavefunc is a nop, ignore this transform
9204                         if (!dynamicvertex)
9205                         {
9206                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9207                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9208                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9209                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9210                         }
9211                         dynamicvertex = true;
9212                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9213                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9214                         break;
9215                 case Q3DEFORM_BULGE:
9216                         if (!dynamicvertex)
9217                         {
9218                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9219                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9220                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9221                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9222                         }
9223                         dynamicvertex = true;
9224                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9225                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9226                         break;
9227                 case Q3DEFORM_MOVE:
9228                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9229                                 break; // if wavefunc is a nop, ignore this transform
9230                         if (!dynamicvertex)
9231                         {
9232                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_move] += 1;
9233                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9234                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9235                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9236                         }
9237                         dynamicvertex = true;
9238                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9239                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9240                         break;
9241                 }
9242         }
9243         switch(rsurface.texture->tcgen.tcgen)
9244         {
9245         default:
9246         case Q3TCGEN_TEXTURE:
9247                 break;
9248         case Q3TCGEN_LIGHTMAP:
9249                 if (!dynamicvertex)
9250                 {
9251                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9252                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9253                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9254                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9255                 }
9256                 dynamicvertex = true;
9257                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9258                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9259                 break;
9260         case Q3TCGEN_VECTOR:
9261                 if (!dynamicvertex)
9262                 {
9263                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9264                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9265                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9266                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9267                 }
9268                 dynamicvertex = true;
9269                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9270                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9271                 break;
9272         case Q3TCGEN_ENVIRONMENT:
9273                 if (!dynamicvertex)
9274                 {
9275                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9276                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9277                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9278                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9279                 }
9280                 dynamicvertex = true;
9281                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9282                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9283                 break;
9284         }
9285         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9286         {
9287                 if (!dynamicvertex)
9288                 {
9289                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9290                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9291                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9292                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9293                 }
9294                 dynamicvertex = true;
9295                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9296                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9297         }
9298
9299         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9300         {
9301                 if (!dynamicvertex)
9302                 {
9303                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9304                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9305                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9306                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9307                 }
9308                 dynamicvertex = true;
9309                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9310         }
9311
9312         // when the model data has no vertex buffer (dynamic mesh), we need to
9313         // eliminate gaps
9314         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9315                 batchneed |= BATCHNEED_NOGAPS;
9316
9317         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9318         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9319         // we ensure this by treating the vertex batch as dynamic...
9320         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9321         {
9322                 if (!dynamicvertex)
9323                 {
9324                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9325                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9326                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9327                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9328                 }
9329                 dynamicvertex = true;
9330         }
9331
9332         if (dynamicvertex)
9333         {
9334                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9335                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9336                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9337                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9338                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9339                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9340                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9341                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9342         }
9343
9344         // if needsupdate, we have to do a dynamic vertex batch for sure
9345         if (needsupdate & batchneed)
9346         {
9347                 if (!dynamicvertex)
9348                 {
9349                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9350                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9351                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9352                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9353                 }
9354                 dynamicvertex = true;
9355         }
9356
9357         // see if we need to build vertexmesh from arrays
9358         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9359         {
9360                 if (!dynamicvertex)
9361                 {
9362                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9363                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9364                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9365                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9366                 }
9367                 dynamicvertex = true;
9368         }
9369
9370         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9371         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9372                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9373
9374         rsurface.batchvertex3f = rsurface.modelvertex3f;
9375         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9376         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9377         rsurface.batchsvector3f = rsurface.modelsvector3f;
9378         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9379         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9380         rsurface.batchtvector3f = rsurface.modeltvector3f;
9381         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9382         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9383         rsurface.batchnormal3f = rsurface.modelnormal3f;
9384         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9385         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9386         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9387         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9388         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9389         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9390         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9391         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9392         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9393         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9394         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9395         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9396         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9397         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9398         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9399         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9400         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9401         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9402         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9403         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9404         rsurface.batchelement3i = rsurface.modelelement3i;
9405         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9406         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9407         rsurface.batchelement3s = rsurface.modelelement3s;
9408         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9409         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9410         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9411         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9412         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9413         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9414         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9415
9416         // if any dynamic vertex processing has to occur in software, we copy the
9417         // entire surface list together before processing to rebase the vertices
9418         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9419         //
9420         // if any gaps exist and we do not have a static vertex buffer, we have to
9421         // copy the surface list together to avoid wasting upload bandwidth on the
9422         // vertices in the gaps.
9423         //
9424         // if gaps exist and we have a static vertex buffer, we can choose whether
9425         // to combine the index buffer ranges into one dynamic index buffer or
9426         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9427         //
9428         // in many cases the batch is reduced to one draw call.
9429
9430         rsurface.batchmultidraw = false;
9431         rsurface.batchmultidrawnumsurfaces = 0;
9432         rsurface.batchmultidrawsurfacelist = NULL;
9433
9434         if (!dynamicvertex)
9435         {
9436                 // static vertex data, just set pointers...
9437                 rsurface.batchgeneratedvertex = false;
9438                 // if there are gaps, we want to build a combined index buffer,
9439                 // otherwise use the original static buffer with an appropriate offset
9440                 if (gaps)
9441                 {
9442                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9443                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9444                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9445                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9446                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9447                         {
9448                                 rsurface.batchmultidraw = true;
9449                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9450                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9451                                 return;
9452                         }
9453                         // build a new triangle elements array for this batch
9454                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9455                         rsurface.batchfirsttriangle = 0;
9456                         numtriangles = 0;
9457                         for (i = 0;i < texturenumsurfaces;i++)
9458                         {
9459                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9460                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9461                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9462                                 numtriangles += surfacenumtriangles;
9463                         }
9464                         rsurface.batchelement3i_indexbuffer = NULL;
9465                         rsurface.batchelement3i_bufferoffset = 0;
9466                         rsurface.batchelement3s = NULL;
9467                         rsurface.batchelement3s_indexbuffer = NULL;
9468                         rsurface.batchelement3s_bufferoffset = 0;
9469                         if (endvertex <= 65536)
9470                         {
9471                                 // make a 16bit (unsigned short) index array if possible
9472                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9473                                 for (i = 0;i < numtriangles*3;i++)
9474                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9475                         }
9476                         // upload buffer data for the copytriangles batch
9477                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9478                         {
9479                                 if (rsurface.batchelement3s)
9480                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9481                                 else if (rsurface.batchelement3i)
9482                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9483                         }
9484                 }
9485                 else
9486                 {
9487                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9488                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9489                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9490                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9491                 }
9492                 return;
9493         }
9494
9495         // something needs software processing, do it for real...
9496         // we only directly handle separate array data in this case and then
9497         // generate interleaved data if needed...
9498         rsurface.batchgeneratedvertex = true;
9499         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9500         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9501         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9502         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9503
9504         // now copy the vertex data into a combined array and make an index array
9505         // (this is what Quake3 does all the time)
9506         // we also apply any skeletal animation here that would have been done in
9507         // the vertex shader, because most of the dynamic vertex animation cases
9508         // need actual vertex positions and normals
9509         //if (dynamicvertex)
9510         {
9511                 rsurface.batchvertexmesh = NULL;
9512                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9513                 rsurface.batchvertexmesh_bufferoffset = 0;
9514                 rsurface.batchvertex3f = NULL;
9515                 rsurface.batchvertex3f_vertexbuffer = NULL;
9516                 rsurface.batchvertex3f_bufferoffset = 0;
9517                 rsurface.batchsvector3f = NULL;
9518                 rsurface.batchsvector3f_vertexbuffer = NULL;
9519                 rsurface.batchsvector3f_bufferoffset = 0;
9520                 rsurface.batchtvector3f = NULL;
9521                 rsurface.batchtvector3f_vertexbuffer = NULL;
9522                 rsurface.batchtvector3f_bufferoffset = 0;
9523                 rsurface.batchnormal3f = NULL;
9524                 rsurface.batchnormal3f_vertexbuffer = NULL;
9525                 rsurface.batchnormal3f_bufferoffset = 0;
9526                 rsurface.batchlightmapcolor4f = NULL;
9527                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9528                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9529                 rsurface.batchtexcoordtexture2f = NULL;
9530                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9531                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9532                 rsurface.batchtexcoordlightmap2f = NULL;
9533                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9534                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9535                 rsurface.batchskeletalindex4ub = NULL;
9536                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9537                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9538                 rsurface.batchskeletalweight4ub = NULL;
9539                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9540                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9541                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9542                 rsurface.batchelement3i_indexbuffer = NULL;
9543                 rsurface.batchelement3i_bufferoffset = 0;
9544                 rsurface.batchelement3s = NULL;
9545                 rsurface.batchelement3s_indexbuffer = NULL;
9546                 rsurface.batchelement3s_bufferoffset = 0;
9547                 rsurface.batchskeletaltransform3x4buffer = NULL;
9548                 rsurface.batchskeletaltransform3x4offset = 0;
9549                 rsurface.batchskeletaltransform3x4size = 0;
9550                 // we'll only be setting up certain arrays as needed
9551                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9552                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9553                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9554                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9555                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9556                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9557                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9558                 {
9559                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9560                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9561                 }
9562                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9563                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9564                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9565                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9566                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9567                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9568                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9569                 {
9570                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9571                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9572                 }
9573                 numvertices = 0;
9574                 numtriangles = 0;
9575                 for (i = 0;i < texturenumsurfaces;i++)
9576                 {
9577                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9578                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9579                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9580                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9581                         // copy only the data requested
9582                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9583                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9584                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9585                         {
9586                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9587                                 {
9588                                         if (rsurface.batchvertex3f)
9589                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9590                                         else
9591                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9592                                 }
9593                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9594                                 {
9595                                         if (rsurface.modelnormal3f)
9596                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9597                                         else
9598                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9599                                 }
9600                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9601                                 {
9602                                         if (rsurface.modelsvector3f)
9603                                         {
9604                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9605                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9606                                         }
9607                                         else
9608                                         {
9609                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9610                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9611                                         }
9612                                 }
9613                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9614                                 {
9615                                         if (rsurface.modellightmapcolor4f)
9616                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9617                                         else
9618                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9619                                 }
9620                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9621                                 {
9622                                         if (rsurface.modeltexcoordtexture2f)
9623                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9624                                         else
9625                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9626                                 }
9627                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9628                                 {
9629                                         if (rsurface.modeltexcoordlightmap2f)
9630                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9631                                         else
9632                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9633                                 }
9634                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9635                                 {
9636                                         if (rsurface.modelskeletalindex4ub)
9637                                         {
9638                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9639                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9640                                         }
9641                                         else
9642                                         {
9643                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9644                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9645                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9646                                                 for (j = 0;j < surfacenumvertices;j++)
9647                                                         ub[j*4] = 255;
9648                                         }
9649                                 }
9650                         }
9651                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9652                         numvertices += surfacenumvertices;
9653                         numtriangles += surfacenumtriangles;
9654                 }
9655
9656                 // generate a 16bit index array as well if possible
9657                 // (in general, dynamic batches fit)
9658                 if (numvertices <= 65536)
9659                 {
9660                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9661                         for (i = 0;i < numtriangles*3;i++)
9662                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9663                 }
9664
9665                 // since we've copied everything, the batch now starts at 0
9666                 rsurface.batchfirstvertex = 0;
9667                 rsurface.batchnumvertices = batchnumvertices;
9668                 rsurface.batchfirsttriangle = 0;
9669                 rsurface.batchnumtriangles = batchnumtriangles;
9670         }
9671
9672         // apply skeletal animation that would have been done in the vertex shader
9673         if (rsurface.batchskeletaltransform3x4)
9674         {
9675                 const unsigned char *si;
9676                 const unsigned char *sw;
9677                 const float *t[4];
9678                 const float *b = rsurface.batchskeletaltransform3x4;
9679                 float *vp, *vs, *vt, *vn;
9680                 float w[4];
9681                 float m[3][4], n[3][4];
9682                 float tp[3], ts[3], tt[3], tn[3];
9683                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9684                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9685                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9686                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9687                 si = rsurface.batchskeletalindex4ub;
9688                 sw = rsurface.batchskeletalweight4ub;
9689                 vp = rsurface.batchvertex3f;
9690                 vs = rsurface.batchsvector3f;
9691                 vt = rsurface.batchtvector3f;
9692                 vn = rsurface.batchnormal3f;
9693                 memset(m[0], 0, sizeof(m));
9694                 memset(n[0], 0, sizeof(n));
9695                 for (i = 0;i < batchnumvertices;i++)
9696                 {
9697                         t[0] = b + si[0]*12;
9698                         if (sw[0] == 255)
9699                         {
9700                                 // common case - only one matrix
9701                                 m[0][0] = t[0][ 0];
9702                                 m[0][1] = t[0][ 1];
9703                                 m[0][2] = t[0][ 2];
9704                                 m[0][3] = t[0][ 3];
9705                                 m[1][0] = t[0][ 4];
9706                                 m[1][1] = t[0][ 5];
9707                                 m[1][2] = t[0][ 6];
9708                                 m[1][3] = t[0][ 7];
9709                                 m[2][0] = t[0][ 8];
9710                                 m[2][1] = t[0][ 9];
9711                                 m[2][2] = t[0][10];
9712                                 m[2][3] = t[0][11];
9713                         }
9714                         else if (sw[2] + sw[3])
9715                         {
9716                                 // blend 4 matrices
9717                                 t[1] = b + si[1]*12;
9718                                 t[2] = b + si[2]*12;
9719                                 t[3] = b + si[3]*12;
9720                                 w[0] = sw[0] * (1.0f / 255.0f);
9721                                 w[1] = sw[1] * (1.0f / 255.0f);
9722                                 w[2] = sw[2] * (1.0f / 255.0f);
9723                                 w[3] = sw[3] * (1.0f / 255.0f);
9724                                 // blend the matrices
9725                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9726                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9727                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9728                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9729                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9730                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9731                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9732                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9733                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9734                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9735                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9736                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9737                         }
9738                         else
9739                         {
9740                                 // blend 2 matrices
9741                                 t[1] = b + si[1]*12;
9742                                 w[0] = sw[0] * (1.0f / 255.0f);
9743                                 w[1] = sw[1] * (1.0f / 255.0f);
9744                                 // blend the matrices
9745                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9746                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9747                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9748                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9749                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9750                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9751                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9752                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9753                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9754                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9755                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9756                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9757                         }
9758                         si += 4;
9759                         sw += 4;
9760                         // modify the vertex
9761                         VectorCopy(vp, tp);
9762                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9763                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9764                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9765                         vp += 3;
9766                         if (vn)
9767                         {
9768                                 // the normal transformation matrix is a set of cross products...
9769                                 CrossProduct(m[1], m[2], n[0]);
9770                                 CrossProduct(m[2], m[0], n[1]);
9771                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9772                                 VectorCopy(vn, tn);
9773                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9774                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9775                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9776                                 VectorNormalize(vn);
9777                                 vn += 3;
9778                                 if (vs)
9779                                 {
9780                                         VectorCopy(vs, ts);
9781                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9782                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9783                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9784                                         VectorNormalize(vs);
9785                                         vs += 3;
9786                                         VectorCopy(vt, tt);
9787                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9788                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9789                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9790                                         VectorNormalize(vt);
9791                                         vt += 3;
9792                                 }
9793                         }
9794                 }
9795                 rsurface.batchskeletaltransform3x4 = NULL;
9796                 rsurface.batchskeletalnumtransforms = 0;
9797         }
9798
9799         // q1bsp surfaces rendered in vertex color mode have to have colors
9800         // calculated based on lightstyles
9801         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9802         {
9803                 // generate color arrays for the surfaces in this list
9804                 int c[4];
9805                 int scale;
9806                 int size3;
9807                 const int *offsets;
9808                 const unsigned char *lm;
9809                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9810                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9811                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9812                 numvertices = 0;
9813                 for (i = 0;i < texturenumsurfaces;i++)
9814                 {
9815                         surface = texturesurfacelist[i];
9816                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9817                         surfacenumvertices = surface->num_vertices;
9818                         if (surface->lightmapinfo->samples)
9819                         {
9820                                 for (j = 0;j < surfacenumvertices;j++)
9821                                 {
9822                                         lm = surface->lightmapinfo->samples + offsets[j];
9823                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9824                                         VectorScale(lm, scale, c);
9825                                         if (surface->lightmapinfo->styles[1] != 255)
9826                                         {
9827                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9828                                                 lm += size3;
9829                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9830                                                 VectorMA(c, scale, lm, c);
9831                                                 if (surface->lightmapinfo->styles[2] != 255)
9832                                                 {
9833                                                         lm += size3;
9834                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9835                                                         VectorMA(c, scale, lm, c);
9836                                                         if (surface->lightmapinfo->styles[3] != 255)
9837                                                         {
9838                                                                 lm += size3;
9839                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9840                                                                 VectorMA(c, scale, lm, c);
9841                                                         }
9842                                                 }
9843                                         }
9844                                         c[0] >>= 7;
9845                                         c[1] >>= 7;
9846                                         c[2] >>= 7;
9847                                         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);
9848                                         numvertices++;
9849                                 }
9850                         }
9851                         else
9852                         {
9853                                 for (j = 0;j < surfacenumvertices;j++)
9854                                 {
9855                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9856                                         numvertices++;
9857                                 }
9858                         }
9859                 }
9860         }
9861
9862         // if vertices are deformed (sprite flares and things in maps, possibly
9863         // water waves, bulges and other deformations), modify the copied vertices
9864         // in place
9865         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9866         {
9867                 switch (deform->deform)
9868                 {
9869                 default:
9870                 case Q3DEFORM_PROJECTIONSHADOW:
9871                 case Q3DEFORM_TEXT0:
9872                 case Q3DEFORM_TEXT1:
9873                 case Q3DEFORM_TEXT2:
9874                 case Q3DEFORM_TEXT3:
9875                 case Q3DEFORM_TEXT4:
9876                 case Q3DEFORM_TEXT5:
9877                 case Q3DEFORM_TEXT6:
9878                 case Q3DEFORM_TEXT7:
9879                 case Q3DEFORM_NONE:
9880                         break;
9881                 case Q3DEFORM_AUTOSPRITE:
9882                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9883                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9884                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9885                         VectorNormalize(newforward);
9886                         VectorNormalize(newright);
9887                         VectorNormalize(newup);
9888 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9889 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9890 //                      rsurface.batchvertex3f_bufferoffset = 0;
9891 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9892 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9893 //                      rsurface.batchsvector3f_bufferoffset = 0;
9894 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9895 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9896 //                      rsurface.batchtvector3f_bufferoffset = 0;
9897 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9898 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9899 //                      rsurface.batchnormal3f_bufferoffset = 0;
9900                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9901                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9902                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9903                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9904                                 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);
9905                         // a single autosprite surface can contain multiple sprites...
9906                         for (j = 0;j < batchnumvertices - 3;j += 4)
9907                         {
9908                                 VectorClear(center);
9909                                 for (i = 0;i < 4;i++)
9910                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9911                                 VectorScale(center, 0.25f, center);
9912                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9913                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9914                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9915                                 for (i = 0;i < 4;i++)
9916                                 {
9917                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9918                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9919                                 }
9920                         }
9921                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9922                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9923                         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);
9924                         break;
9925                 case Q3DEFORM_AUTOSPRITE2:
9926                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9927                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9928                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9929                         VectorNormalize(newforward);
9930                         VectorNormalize(newright);
9931                         VectorNormalize(newup);
9932 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9933 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9934 //                      rsurface.batchvertex3f_bufferoffset = 0;
9935                         {
9936                                 const float *v1, *v2;
9937                                 vec3_t start, end;
9938                                 float f, l;
9939                                 struct
9940                                 {
9941                                         float length2;
9942                                         const float *v1;
9943                                         const float *v2;
9944                                 }
9945                                 shortest[2];
9946                                 memset(shortest, 0, sizeof(shortest));
9947                                 // a single autosprite surface can contain multiple sprites...
9948                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9949                                 {
9950                                         VectorClear(center);
9951                                         for (i = 0;i < 4;i++)
9952                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9953                                         VectorScale(center, 0.25f, center);
9954                                         // find the two shortest edges, then use them to define the
9955                                         // axis vectors for rotating around the central axis
9956                                         for (i = 0;i < 6;i++)
9957                                         {
9958                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9959                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9960                                                 l = VectorDistance2(v1, v2);
9961                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9962                                                 if (v1[2] != v2[2])
9963                                                         l += (1.0f / 1024.0f);
9964                                                 if (shortest[0].length2 > l || i == 0)
9965                                                 {
9966                                                         shortest[1] = shortest[0];
9967                                                         shortest[0].length2 = l;
9968                                                         shortest[0].v1 = v1;
9969                                                         shortest[0].v2 = v2;
9970                                                 }
9971                                                 else if (shortest[1].length2 > l || i == 1)
9972                                                 {
9973                                                         shortest[1].length2 = l;
9974                                                         shortest[1].v1 = v1;
9975                                                         shortest[1].v2 = v2;
9976                                                 }
9977                                         }
9978                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9979                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9980                                         // this calculates the right vector from the shortest edge
9981                                         // and the up vector from the edge midpoints
9982                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9983                                         VectorNormalize(right);
9984                                         VectorSubtract(end, start, up);
9985                                         VectorNormalize(up);
9986                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9987                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9988                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9989                                         VectorNegate(forward, forward);
9990                                         VectorReflect(forward, 0, up, forward);
9991                                         VectorNormalize(forward);
9992                                         CrossProduct(up, forward, newright);
9993                                         VectorNormalize(newright);
9994                                         // rotate the quad around the up axis vector, this is made
9995                                         // especially easy by the fact we know the quad is flat,
9996                                         // so we only have to subtract the center position and
9997                                         // measure distance along the right vector, and then
9998                                         // multiply that by the newright vector and add back the
9999                                         // center position
10000                                         // we also need to subtract the old position to undo the
10001                                         // displacement from the center, which we do with a
10002                                         // DotProduct, the subtraction/addition of center is also
10003                                         // optimized into DotProducts here
10004                                         l = DotProduct(right, center);
10005                                         for (i = 0;i < 4;i++)
10006                                         {
10007                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
10008                                                 f = DotProduct(right, v1) - l;
10009                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
10010                                         }
10011                                 }
10012                         }
10013                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
10014                         {
10015 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10016 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
10017 //                              rsurface.batchnormal3f_bufferoffset = 0;
10018                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10019                         }
10020                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10021                         {
10022 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10023 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10024 //                              rsurface.batchsvector3f_bufferoffset = 0;
10025 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10026 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10027 //                              rsurface.batchtvector3f_bufferoffset = 0;
10028                                 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);
10029                         }
10030                         break;
10031                 case Q3DEFORM_NORMAL:
10032                         // deform the normals to make reflections wavey
10033                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10034                         rsurface.batchnormal3f_vertexbuffer = NULL;
10035                         rsurface.batchnormal3f_bufferoffset = 0;
10036                         for (j = 0;j < batchnumvertices;j++)
10037                         {
10038                                 float vertex[3];
10039                                 float *normal = rsurface.batchnormal3f + 3*j;
10040                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10041                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10042                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10043                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10044                                 VectorNormalize(normal);
10045                         }
10046                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10047                         {
10048 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10049 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10050 //                              rsurface.batchsvector3f_bufferoffset = 0;
10051 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10052 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10053 //                              rsurface.batchtvector3f_bufferoffset = 0;
10054                                 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);
10055                         }
10056                         break;
10057                 case Q3DEFORM_WAVE:
10058                         // deform vertex array to make wavey water and flags and such
10059                         waveparms[0] = deform->waveparms[0];
10060                         waveparms[1] = deform->waveparms[1];
10061                         waveparms[2] = deform->waveparms[2];
10062                         waveparms[3] = deform->waveparms[3];
10063                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10064                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10065                         // this is how a divisor of vertex influence on deformation
10066                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10067                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10068 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10069 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10070 //                      rsurface.batchvertex3f_bufferoffset = 0;
10071 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10072 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10073 //                      rsurface.batchnormal3f_bufferoffset = 0;
10074                         for (j = 0;j < batchnumvertices;j++)
10075                         {
10076                                 // if the wavefunc depends on time, evaluate it per-vertex
10077                                 if (waveparms[3])
10078                                 {
10079                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10080                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10081                                 }
10082                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10083                         }
10084                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10085                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10086                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10087                         {
10088 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10089 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10090 //                              rsurface.batchsvector3f_bufferoffset = 0;
10091 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10092 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10093 //                              rsurface.batchtvector3f_bufferoffset = 0;
10094                                 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);
10095                         }
10096                         break;
10097                 case Q3DEFORM_BULGE:
10098                         // deform vertex array to make the surface have moving bulges
10099 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10100 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10101 //                      rsurface.batchvertex3f_bufferoffset = 0;
10102 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10103 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10104 //                      rsurface.batchnormal3f_bufferoffset = 0;
10105                         for (j = 0;j < batchnumvertices;j++)
10106                         {
10107                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
10108                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10109                         }
10110                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10111                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10112                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10113                         {
10114 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10115 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10116 //                              rsurface.batchsvector3f_bufferoffset = 0;
10117 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10118 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10119 //                              rsurface.batchtvector3f_bufferoffset = 0;
10120                                 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);
10121                         }
10122                         break;
10123                 case Q3DEFORM_MOVE:
10124                         // deform vertex array
10125                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10126                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10127                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10128                         VectorScale(deform->parms, scale, waveparms);
10129 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10130 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10131 //                      rsurface.batchvertex3f_bufferoffset = 0;
10132                         for (j = 0;j < batchnumvertices;j++)
10133                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10134                         break;
10135                 }
10136         }
10137
10138         if (rsurface.batchtexcoordtexture2f)
10139         {
10140         // generate texcoords based on the chosen texcoord source
10141                 switch(rsurface.texture->tcgen.tcgen)
10142                 {
10143                 default:
10144                 case Q3TCGEN_TEXTURE:
10145                         break;
10146                 case Q3TCGEN_LIGHTMAP:
10147         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10148         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10149         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10150                         if (rsurface.batchtexcoordlightmap2f)
10151                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10152                         break;
10153                 case Q3TCGEN_VECTOR:
10154         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10155         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10156         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10157                         for (j = 0;j < batchnumvertices;j++)
10158                         {
10159                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10160                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10161                         }
10162                         break;
10163                 case Q3TCGEN_ENVIRONMENT:
10164                         // make environment reflections using a spheremap
10165                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10166                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10167                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10168                         for (j = 0;j < batchnumvertices;j++)
10169                         {
10170                                 // identical to Q3A's method, but executed in worldspace so
10171                                 // carried models can be shiny too
10172
10173                                 float viewer[3], d, reflected[3], worldreflected[3];
10174
10175                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10176                                 // VectorNormalize(viewer);
10177
10178                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10179
10180                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10181                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10182                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10183                                 // note: this is proportinal to viewer, so we can normalize later
10184
10185                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10186                                 VectorNormalize(worldreflected);
10187
10188                                 // note: this sphere map only uses world x and z!
10189                                 // so positive and negative y will LOOK THE SAME.
10190                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10191                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10192                         }
10193                         break;
10194                 }
10195                 // the only tcmod that needs software vertex processing is turbulent, so
10196                 // check for it here and apply the changes if needed
10197                 // and we only support that as the first one
10198                 // (handling a mixture of turbulent and other tcmods would be problematic
10199                 //  without punting it entirely to a software path)
10200                 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10201                 {
10202                         amplitude = rsurface.texture->tcmods[0].parms[1];
10203                         animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10204         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10205         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10206         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10207                         for (j = 0;j < batchnumvertices;j++)
10208                         {
10209                                 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);
10210                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10211                         }
10212                 }
10213         }
10214
10215         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10216         {
10217                 // convert the modified arrays to vertex structs
10218 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10219 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10220 //              rsurface.batchvertexmesh_bufferoffset = 0;
10221                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10222                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10223                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10224                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10225                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10226                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10227                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10228                 {
10229                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10230                         {
10231                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10232                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10233                         }
10234                 }
10235                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10236                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10237                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10238                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10239                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10240                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10241                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10242                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10243                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10244                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10245                 {
10246                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10247                         {
10248                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10249                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10250                         }
10251                 }
10252         }
10253
10254         // upload buffer data for the dynamic batch
10255         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10256         {
10257                 if (rsurface.batchvertexmesh)
10258                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10259                 else
10260                 {
10261                         if (rsurface.batchvertex3f)
10262                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10263                         if (rsurface.batchsvector3f)
10264                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10265                         if (rsurface.batchtvector3f)
10266                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10267                         if (rsurface.batchnormal3f)
10268                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10269                         if (rsurface.batchlightmapcolor4f)
10270                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10271                         if (rsurface.batchtexcoordtexture2f)
10272                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10273                         if (rsurface.batchtexcoordlightmap2f)
10274                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10275                         if (rsurface.batchskeletalindex4ub)
10276                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10277                         if (rsurface.batchskeletalweight4ub)
10278                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10279                 }
10280                 if (rsurface.batchelement3s)
10281                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10282                 else if (rsurface.batchelement3i)
10283                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10284         }
10285 }
10286
10287 void RSurf_DrawBatch(void)
10288 {
10289         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10290         // through the pipeline, killing it earlier in the pipeline would have
10291         // per-surface overhead rather than per-batch overhead, so it's best to
10292         // reject it here, before it hits glDraw.
10293         if (rsurface.batchnumtriangles == 0)
10294                 return;
10295 #if 0
10296         // batch debugging code
10297         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10298         {
10299                 int i;
10300                 int j;
10301                 int c;
10302                 const int *e;
10303                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10304                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10305                 {
10306                         c = e[i];
10307                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10308                         {
10309                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10310                                 {
10311                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10312                                                 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);
10313                                         break;
10314                                 }
10315                         }
10316                 }
10317         }
10318 #endif
10319         if (rsurface.batchmultidraw)
10320         {
10321                 // issue multiple draws rather than copying index data
10322                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10323                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10324                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10325                 for (i = 0;i < numsurfaces;)
10326                 {
10327                         // combine consecutive surfaces as one draw
10328                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10329                                 if (surfacelist[j] != surfacelist[k] + 1)
10330                                         break;
10331                         firstvertex = surfacelist[i]->num_firstvertex;
10332                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10333                         firsttriangle = surfacelist[i]->num_firsttriangle;
10334                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10335                         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);
10336                         i = j;
10337                 }
10338         }
10339         else
10340         {
10341                 // there is only one consecutive run of index data (may have been combined)
10342                 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);
10343         }
10344 }
10345
10346 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10347 {
10348         // pick the closest matching water plane
10349         int planeindex, vertexindex, bestplaneindex = -1;
10350         float d, bestd;
10351         vec3_t vert;
10352         const float *v;
10353         r_waterstate_waterplane_t *p;
10354         qboolean prepared = false;
10355         bestd = 0;
10356         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10357         {
10358                 if(p->camera_entity != rsurface.texture->camera_entity)
10359                         continue;
10360                 d = 0;
10361                 if(!prepared)
10362                 {
10363                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10364                         prepared = true;
10365                         if(rsurface.batchnumvertices == 0)
10366                                 break;
10367                 }
10368                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10369                 {
10370                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10371                         d += fabs(PlaneDiff(vert, &p->plane));
10372                 }
10373                 if (bestd > d || bestplaneindex < 0)
10374                 {
10375                         bestd = d;
10376                         bestplaneindex = planeindex;
10377                 }
10378         }
10379         return bestplaneindex;
10380         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10381         // this situation though, as it might be better to render single larger
10382         // batches with useless stuff (backface culled for example) than to
10383         // render multiple smaller batches
10384 }
10385
10386 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10387 {
10388         int i;
10389         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10390         rsurface.passcolor4f_vertexbuffer = 0;
10391         rsurface.passcolor4f_bufferoffset = 0;
10392         for (i = 0;i < rsurface.batchnumvertices;i++)
10393                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10394 }
10395
10396 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10397 {
10398         int i;
10399         float f;
10400         const float *v;
10401         const float *c;
10402         float *c2;
10403         if (rsurface.passcolor4f)
10404         {
10405                 // generate color arrays
10406                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10407                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10408                 rsurface.passcolor4f_vertexbuffer = 0;
10409                 rsurface.passcolor4f_bufferoffset = 0;
10410                 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)
10411                 {
10412                         f = RSurf_FogVertex(v);
10413                         c2[0] = c[0] * f;
10414                         c2[1] = c[1] * f;
10415                         c2[2] = c[2] * f;
10416                         c2[3] = c[3];
10417                 }
10418         }
10419         else
10420         {
10421                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10422                 rsurface.passcolor4f_vertexbuffer = 0;
10423                 rsurface.passcolor4f_bufferoffset = 0;
10424                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10425                 {
10426                         f = RSurf_FogVertex(v);
10427                         c2[0] = f;
10428                         c2[1] = f;
10429                         c2[2] = f;
10430                         c2[3] = 1;
10431                 }
10432         }
10433 }
10434
10435 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10436 {
10437         int i;
10438         float f;
10439         const float *v;
10440         const float *c;
10441         float *c2;
10442         if (!rsurface.passcolor4f)
10443                 return;
10444         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10445         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10446         rsurface.passcolor4f_vertexbuffer = 0;
10447         rsurface.passcolor4f_bufferoffset = 0;
10448         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)
10449         {
10450                 f = RSurf_FogVertex(v);
10451                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10452                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10453                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10454                 c2[3] = c[3];
10455         }
10456 }
10457
10458 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10459 {
10460         int i;
10461         const float *c;
10462         float *c2;
10463         if (!rsurface.passcolor4f)
10464                 return;
10465         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10466         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10467         rsurface.passcolor4f_vertexbuffer = 0;
10468         rsurface.passcolor4f_bufferoffset = 0;
10469         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10470         {
10471                 c2[0] = c[0] * r;
10472                 c2[1] = c[1] * g;
10473                 c2[2] = c[2] * b;
10474                 c2[3] = c[3] * a;
10475         }
10476 }
10477
10478 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10479 {
10480         int i;
10481         const float *c;
10482         float *c2;
10483         if (!rsurface.passcolor4f)
10484                 return;
10485         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10486         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10487         rsurface.passcolor4f_vertexbuffer = 0;
10488         rsurface.passcolor4f_bufferoffset = 0;
10489         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10490         {
10491                 c2[0] = c[0] + r_refdef.scene.ambient;
10492                 c2[1] = c[1] + r_refdef.scene.ambient;
10493                 c2[2] = c[2] + r_refdef.scene.ambient;
10494                 c2[3] = c[3];
10495         }
10496 }
10497
10498 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10499 {
10500         // TODO: optimize
10501         rsurface.passcolor4f = NULL;
10502         rsurface.passcolor4f_vertexbuffer = 0;
10503         rsurface.passcolor4f_bufferoffset = 0;
10504         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10505         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10506         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10507         GL_Color(r, g, b, a);
10508         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10509         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10510         R_Mesh_TexMatrix(0, NULL);
10511         RSurf_DrawBatch();
10512 }
10513
10514 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10515 {
10516         // TODO: optimize applyfog && applycolor case
10517         // just apply fog if necessary, and tint the fog color array if necessary
10518         rsurface.passcolor4f = NULL;
10519         rsurface.passcolor4f_vertexbuffer = 0;
10520         rsurface.passcolor4f_bufferoffset = 0;
10521         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10522         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10523         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10524         GL_Color(r, g, b, a);
10525         RSurf_DrawBatch();
10526 }
10527
10528 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10529 {
10530         // TODO: optimize
10531         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10532         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10533         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10534         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10535         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10536         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10537         GL_Color(r, g, b, a);
10538         RSurf_DrawBatch();
10539 }
10540
10541 static void RSurf_DrawBatch_GL11_ClampColor(void)
10542 {
10543         int i;
10544         const float *c1;
10545         float *c2;
10546         if (!rsurface.passcolor4f)
10547                 return;
10548         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10549         {
10550                 c2[0] = bound(0.0f, c1[0], 1.0f);
10551                 c2[1] = bound(0.0f, c1[1], 1.0f);
10552                 c2[2] = bound(0.0f, c1[2], 1.0f);
10553                 c2[3] = bound(0.0f, c1[3], 1.0f);
10554         }
10555 }
10556
10557 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10558 {
10559         int i;
10560         float f;
10561         const float *v;
10562         const float *n;
10563         float *c;
10564         //vec3_t eyedir;
10565
10566         // fake shading
10567         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10568         rsurface.passcolor4f_vertexbuffer = 0;
10569         rsurface.passcolor4f_bufferoffset = 0;
10570         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)
10571         {
10572                 f = -DotProduct(r_refdef.view.forward, n);
10573                 f = max(0, f);
10574                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10575                 f *= r_refdef.lightmapintensity;
10576                 Vector4Set(c, f, f, f, 1);
10577         }
10578 }
10579
10580 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10581 {
10582         RSurf_DrawBatch_GL11_ApplyFakeLight();
10583         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10584         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10585         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10586         GL_Color(r, g, b, a);
10587         RSurf_DrawBatch();
10588 }
10589
10590 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10591 {
10592         int i;
10593         float f;
10594         float alpha;
10595         const float *v;
10596         const float *n;
10597         float *c;
10598         vec3_t ambientcolor;
10599         vec3_t diffusecolor;
10600         vec3_t lightdir;
10601         // TODO: optimize
10602         // model lighting
10603         VectorCopy(rsurface.modellight_lightdir, lightdir);
10604         f = 0.5f * r_refdef.lightmapintensity;
10605         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10606         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10607         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10608         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10609         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10610         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10611         alpha = *a;
10612         if (VectorLength2(diffusecolor) > 0)
10613         {
10614                 // q3-style directional shading
10615                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10616                 rsurface.passcolor4f_vertexbuffer = 0;
10617                 rsurface.passcolor4f_bufferoffset = 0;
10618                 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)
10619                 {
10620                         if ((f = DotProduct(n, lightdir)) > 0)
10621                                 VectorMA(ambientcolor, f, diffusecolor, c);
10622                         else
10623                                 VectorCopy(ambientcolor, c);
10624                         c[3] = alpha;
10625                 }
10626                 *r = 1;
10627                 *g = 1;
10628                 *b = 1;
10629                 *a = 1;
10630                 *applycolor = false;
10631         }
10632         else
10633         {
10634                 *r = ambientcolor[0];
10635                 *g = ambientcolor[1];
10636                 *b = ambientcolor[2];
10637                 rsurface.passcolor4f = NULL;
10638                 rsurface.passcolor4f_vertexbuffer = 0;
10639                 rsurface.passcolor4f_bufferoffset = 0;
10640         }
10641 }
10642
10643 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10644 {
10645         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10646         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10647         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10648         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10649         GL_Color(r, g, b, a);
10650         RSurf_DrawBatch();
10651 }
10652
10653 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10654 {
10655         int i;
10656         float f;
10657         const float *v;
10658         float *c;
10659
10660         // fake shading
10661         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10662         rsurface.passcolor4f_vertexbuffer = 0;
10663         rsurface.passcolor4f_bufferoffset = 0;
10664
10665         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10666         {
10667                 f = 1 - RSurf_FogVertex(v);
10668                 c[0] = r;
10669                 c[1] = g;
10670                 c[2] = b;
10671                 c[3] = f * a;
10672         }
10673 }
10674
10675 void RSurf_SetupDepthAndCulling(void)
10676 {
10677         // submodels are biased to avoid z-fighting with world surfaces that they
10678         // may be exactly overlapping (avoids z-fighting artifacts on certain
10679         // doors and things in Quake maps)
10680         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10681         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10682         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10683         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10684 }
10685
10686 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10687 {
10688         // transparent sky would be ridiculous
10689         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10690                 return;
10691         R_SetupShader_Generic_NoTexture(false, false);
10692         skyrenderlater = true;
10693         RSurf_SetupDepthAndCulling();
10694         GL_DepthMask(true);
10695         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10696         // skymasking on them, and Quake3 never did sky masking (unlike
10697         // software Quake and software Quake2), so disable the sky masking
10698         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10699         // and skymasking also looks very bad when noclipping outside the
10700         // level, so don't use it then either.
10701         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10702         {
10703                 R_Mesh_ResetTextureState();
10704                 if (skyrendermasked)
10705                 {
10706                         R_SetupShader_DepthOrShadow(false, false, false);
10707                         // depth-only (masking)
10708                         GL_ColorMask(0,0,0,0);
10709                         // just to make sure that braindead drivers don't draw
10710                         // anything despite that colormask...
10711                         GL_BlendFunc(GL_ZERO, GL_ONE);
10712                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10713                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10714                 }
10715                 else
10716                 {
10717                         R_SetupShader_Generic_NoTexture(false, false);
10718                         // fog sky
10719                         GL_BlendFunc(GL_ONE, GL_ZERO);
10720                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10721                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10722                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10723                 }
10724                 RSurf_DrawBatch();
10725                 if (skyrendermasked)
10726                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10727         }
10728         R_Mesh_ResetTextureState();
10729         GL_Color(1, 1, 1, 1);
10730 }
10731
10732 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10733 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10734 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10735 {
10736         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10737                 return;
10738         if (prepass)
10739         {
10740                 // render screenspace normalmap to texture
10741                 GL_DepthMask(true);
10742                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10743                 RSurf_DrawBatch();
10744                 return;
10745         }
10746
10747         // bind lightmap texture
10748
10749         // water/refraction/reflection/camera surfaces have to be handled specially
10750         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10751         {
10752                 int start, end, startplaneindex;
10753                 for (start = 0;start < texturenumsurfaces;start = end)
10754                 {
10755                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10756                         if(startplaneindex < 0)
10757                         {
10758                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10759                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10760                                 end = start + 1;
10761                                 continue;
10762                         }
10763                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10764                                 ;
10765                         // now that we have a batch using the same planeindex, render it
10766                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10767                         {
10768                                 // render water or distortion background
10769                                 GL_DepthMask(true);
10770                                 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);
10771                                 RSurf_DrawBatch();
10772                                 // blend surface on top
10773                                 GL_DepthMask(false);
10774                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10775                                 RSurf_DrawBatch();
10776                         }
10777                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10778                         {
10779                                 // render surface with reflection texture as input
10780                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10781                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, (void *)(r_fb.water.waterplanes + startplaneindex), false);
10782                                 RSurf_DrawBatch();
10783                         }
10784                 }
10785                 return;
10786         }
10787
10788         // render surface batch normally
10789         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10790         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);
10791         RSurf_DrawBatch();
10792 }
10793
10794 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10795 {
10796         // OpenGL 1.3 path - anything not completely ancient
10797         qboolean applycolor;
10798         qboolean applyfog;
10799         int layerindex;
10800         const texturelayer_t *layer;
10801         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);
10802         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10803
10804         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10805         {
10806                 vec4_t layercolor;
10807                 int layertexrgbscale;
10808                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10809                 {
10810                         if (layerindex == 0)
10811                                 GL_AlphaTest(true);
10812                         else
10813                         {
10814                                 GL_AlphaTest(false);
10815                                 GL_DepthFunc(GL_EQUAL);
10816                         }
10817                 }
10818                 GL_DepthMask(layer->depthmask && writedepth);
10819                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10820                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10821                 {
10822                         layertexrgbscale = 4;
10823                         VectorScale(layer->color, 0.25f, layercolor);
10824                 }
10825                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10826                 {
10827                         layertexrgbscale = 2;
10828                         VectorScale(layer->color, 0.5f, layercolor);
10829                 }
10830                 else
10831                 {
10832                         layertexrgbscale = 1;
10833                         VectorScale(layer->color, 1.0f, layercolor);
10834                 }
10835                 layercolor[3] = layer->color[3];
10836                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10837                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10838                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10839                 switch (layer->type)
10840                 {
10841                 case TEXTURELAYERTYPE_LITTEXTURE:
10842                         // single-pass lightmapped texture with 2x rgbscale
10843                         R_Mesh_TexBind(0, r_texture_white);
10844                         R_Mesh_TexMatrix(0, NULL);
10845                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10846                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10847                         R_Mesh_TexBind(1, layer->texture);
10848                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10849                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10850                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10851                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10852                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10853                         else if (FAKELIGHT_ENABLED)
10854                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10855                         else if (rsurface.uselightmaptexture)
10856                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10857                         else
10858                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10859                         break;
10860                 case TEXTURELAYERTYPE_TEXTURE:
10861                         // singletexture unlit texture with transparency support
10862                         R_Mesh_TexBind(0, layer->texture);
10863                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10864                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10865                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10866                         R_Mesh_TexBind(1, 0);
10867                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10868                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10869                         break;
10870                 case TEXTURELAYERTYPE_FOG:
10871                         // singletexture fogging
10872                         if (layer->texture)
10873                         {
10874                                 R_Mesh_TexBind(0, layer->texture);
10875                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10876                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10877                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10878                         }
10879                         else
10880                         {
10881                                 R_Mesh_TexBind(0, 0);
10882                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10883                         }
10884                         R_Mesh_TexBind(1, 0);
10885                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10886                         // generate a color array for the fog pass
10887                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10888                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10889                         RSurf_DrawBatch();
10890                         break;
10891                 default:
10892                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10893                 }
10894         }
10895         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10896         {
10897                 GL_DepthFunc(GL_LEQUAL);
10898                 GL_AlphaTest(false);
10899         }
10900 }
10901
10902 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10903 {
10904         // OpenGL 1.1 - crusty old voodoo path
10905         qboolean applyfog;
10906         int layerindex;
10907         const texturelayer_t *layer;
10908         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);
10909         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10910
10911         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10912         {
10913                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10914                 {
10915                         if (layerindex == 0)
10916                                 GL_AlphaTest(true);
10917                         else
10918                         {
10919                                 GL_AlphaTest(false);
10920                                 GL_DepthFunc(GL_EQUAL);
10921                         }
10922                 }
10923                 GL_DepthMask(layer->depthmask && writedepth);
10924                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10925                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10926                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10927                 switch (layer->type)
10928                 {
10929                 case TEXTURELAYERTYPE_LITTEXTURE:
10930                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10931                         {
10932                                 // two-pass lit texture with 2x rgbscale
10933                                 // first the lightmap pass
10934                                 R_Mesh_TexBind(0, r_texture_white);
10935                                 R_Mesh_TexMatrix(0, NULL);
10936                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10937                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10938                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10939                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10940                                 else if (FAKELIGHT_ENABLED)
10941                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10942                                 else if (rsurface.uselightmaptexture)
10943                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10944                                 else
10945                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10946                                 // then apply the texture to it
10947                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10948                                 R_Mesh_TexBind(0, layer->texture);
10949                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10950                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10951                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10952                                 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);
10953                         }
10954                         else
10955                         {
10956                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10957                                 R_Mesh_TexBind(0, layer->texture);
10958                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10959                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10960                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10961                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10962                                         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);
10963                                 else if (FAKELIGHT_ENABLED)
10964                                         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);
10965                                 else
10966                                         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);
10967                         }
10968                         break;
10969                 case TEXTURELAYERTYPE_TEXTURE:
10970                         // singletexture unlit texture with transparency support
10971                         R_Mesh_TexBind(0, layer->texture);
10972                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10973                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10974                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10975                         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);
10976                         break;
10977                 case TEXTURELAYERTYPE_FOG:
10978                         // singletexture fogging
10979                         if (layer->texture)
10980                         {
10981                                 R_Mesh_TexBind(0, layer->texture);
10982                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10983                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10984                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10985                         }
10986                         else
10987                         {
10988                                 R_Mesh_TexBind(0, 0);
10989                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10990                         }
10991                         // generate a color array for the fog pass
10992                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10993                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10994                         RSurf_DrawBatch();
10995                         break;
10996                 default:
10997                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10998                 }
10999         }
11000         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11001         {
11002                 GL_DepthFunc(GL_LEQUAL);
11003                 GL_AlphaTest(false);
11004         }
11005 }
11006
11007 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
11008 {
11009         int vi;
11010         int j;
11011         r_vertexgeneric_t *batchvertex;
11012         float c[4];
11013
11014 //      R_Mesh_ResetTextureState();
11015         R_SetupShader_Generic_NoTexture(false, false);
11016
11017         if(rsurface.texture && rsurface.texture->currentskinframe)
11018         {
11019                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
11020                 c[3] *= rsurface.texture->currentalpha;
11021         }
11022         else
11023         {
11024                 c[0] = 1;
11025                 c[1] = 0;
11026                 c[2] = 1;
11027                 c[3] = 1;
11028         }
11029
11030         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11031         {
11032                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11033                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11034                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11035         }
11036
11037         // brighten it up (as texture value 127 means "unlit")
11038         c[0] *= 2 * r_refdef.view.colorscale;
11039         c[1] *= 2 * r_refdef.view.colorscale;
11040         c[2] *= 2 * r_refdef.view.colorscale;
11041
11042         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11043                 c[3] *= r_wateralpha.value;
11044
11045         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11046         {
11047                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11048                 GL_DepthMask(false);
11049         }
11050         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11051         {
11052                 GL_BlendFunc(GL_ONE, GL_ONE);
11053                 GL_DepthMask(false);
11054         }
11055         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11056         {
11057                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11058                 GL_DepthMask(false);
11059         }
11060         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11061         {
11062                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11063                 GL_DepthMask(false);
11064         }
11065         else
11066         {
11067                 GL_BlendFunc(GL_ONE, GL_ZERO);
11068                 GL_DepthMask(writedepth);
11069         }
11070
11071         if (r_showsurfaces.integer == 3)
11072         {
11073                 rsurface.passcolor4f = NULL;
11074
11075                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11076                 {
11077                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11078
11079                         rsurface.passcolor4f = NULL;
11080                         rsurface.passcolor4f_vertexbuffer = 0;
11081                         rsurface.passcolor4f_bufferoffset = 0;
11082                 }
11083                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11084                 {
11085                         qboolean applycolor = true;
11086                         float one = 1.0;
11087
11088                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11089
11090                         r_refdef.lightmapintensity = 1;
11091                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11092                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11093                 }
11094                 else if (FAKELIGHT_ENABLED)
11095                 {
11096                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11097
11098                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11099                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11100                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11101                 }
11102                 else
11103                 {
11104                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11105
11106                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11107                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11108                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11109                 }
11110
11111                 if(!rsurface.passcolor4f)
11112                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11113
11114                 RSurf_DrawBatch_GL11_ApplyAmbient();
11115                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11116                 if(r_refdef.fogenabled)
11117                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11118                 RSurf_DrawBatch_GL11_ClampColor();
11119
11120                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11121                 R_SetupShader_Generic_NoTexture(false, false);
11122                 RSurf_DrawBatch();
11123         }
11124         else if (!r_refdef.view.showdebug)
11125         {
11126                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11127                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11128                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11129                 {
11130                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11131                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11132                 }
11133                 R_Mesh_PrepareVertices_Generic_Unlock();
11134                 RSurf_DrawBatch();
11135         }
11136         else if (r_showsurfaces.integer == 4)
11137         {
11138                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11139                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11140                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11141                 {
11142                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
11143                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11144                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11145                 }
11146                 R_Mesh_PrepareVertices_Generic_Unlock();
11147                 RSurf_DrawBatch();
11148         }
11149         else if (r_showsurfaces.integer == 2)
11150         {
11151                 const int *e;
11152                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11153                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11154                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11155                 {
11156                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11157                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11158                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11159                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11160                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11161                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11162                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11163                 }
11164                 R_Mesh_PrepareVertices_Generic_Unlock();
11165                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11166         }
11167         else
11168         {
11169                 int texturesurfaceindex;
11170                 int k;
11171                 const msurface_t *surface;
11172                 float surfacecolor4f[4];
11173                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11174                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11175                 vi = 0;
11176                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11177                 {
11178                         surface = texturesurfacelist[texturesurfaceindex];
11179                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11180                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11181                         for (j = 0;j < surface->num_vertices;j++)
11182                         {
11183                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11184                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11185                                 vi++;
11186                         }
11187                 }
11188                 R_Mesh_PrepareVertices_Generic_Unlock();
11189                 RSurf_DrawBatch();
11190         }
11191 }
11192
11193 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11194 {
11195         CHECKGLERROR
11196         RSurf_SetupDepthAndCulling();
11197         if (r_showsurfaces.integer)
11198         {
11199                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11200                 return;
11201         }
11202         switch (vid.renderpath)
11203         {
11204         case RENDERPATH_GL20:
11205         case RENDERPATH_D3D9:
11206         case RENDERPATH_D3D10:
11207         case RENDERPATH_D3D11:
11208         case RENDERPATH_SOFT:
11209         case RENDERPATH_GLES2:
11210                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11211                 break;
11212         case RENDERPATH_GL13:
11213         case RENDERPATH_GLES1:
11214                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11215                 break;
11216         case RENDERPATH_GL11:
11217                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11218                 break;
11219         }
11220         CHECKGLERROR
11221 }
11222
11223 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11224 {
11225         CHECKGLERROR
11226         RSurf_SetupDepthAndCulling();
11227         if (r_showsurfaces.integer)
11228         {
11229                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11230                 return;
11231         }
11232         switch (vid.renderpath)
11233         {
11234         case RENDERPATH_GL20:
11235         case RENDERPATH_D3D9:
11236         case RENDERPATH_D3D10:
11237         case RENDERPATH_D3D11:
11238         case RENDERPATH_SOFT:
11239         case RENDERPATH_GLES2:
11240                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11241                 break;
11242         case RENDERPATH_GL13:
11243         case RENDERPATH_GLES1:
11244                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11245                 break;
11246         case RENDERPATH_GL11:
11247                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11248                 break;
11249         }
11250         CHECKGLERROR
11251 }
11252
11253 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11254 {
11255         int i, j;
11256         int texturenumsurfaces, endsurface;
11257         texture_t *texture;
11258         const msurface_t *surface;
11259         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11260
11261         // if the model is static it doesn't matter what value we give for
11262         // wantnormals and wanttangents, so this logic uses only rules applicable
11263         // to a model, knowing that they are meaningless otherwise
11264         if (ent == r_refdef.scene.worldentity)
11265                 RSurf_ActiveWorldEntity();
11266         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11267                 RSurf_ActiveModelEntity(ent, false, false, false);
11268         else
11269         {
11270                 switch (vid.renderpath)
11271                 {
11272                 case RENDERPATH_GL20:
11273                 case RENDERPATH_D3D9:
11274                 case RENDERPATH_D3D10:
11275                 case RENDERPATH_D3D11:
11276                 case RENDERPATH_SOFT:
11277                 case RENDERPATH_GLES2:
11278                         RSurf_ActiveModelEntity(ent, true, true, false);
11279                         break;
11280                 case RENDERPATH_GL11:
11281                 case RENDERPATH_GL13:
11282                 case RENDERPATH_GLES1:
11283                         RSurf_ActiveModelEntity(ent, true, false, false);
11284                         break;
11285                 }
11286         }
11287
11288         if (r_transparentdepthmasking.integer)
11289         {
11290                 qboolean setup = false;
11291                 for (i = 0;i < numsurfaces;i = j)
11292                 {
11293                         j = i + 1;
11294                         surface = rsurface.modelsurfaces + surfacelist[i];
11295                         texture = surface->texture;
11296                         rsurface.texture = R_GetCurrentTexture(texture);
11297                         rsurface.lightmaptexture = NULL;
11298                         rsurface.deluxemaptexture = NULL;
11299                         rsurface.uselightmaptexture = false;
11300                         // scan ahead until we find a different texture
11301                         endsurface = min(i + 1024, numsurfaces);
11302                         texturenumsurfaces = 0;
11303                         texturesurfacelist[texturenumsurfaces++] = surface;
11304                         for (;j < endsurface;j++)
11305                         {
11306                                 surface = rsurface.modelsurfaces + surfacelist[j];
11307                                 if (texture != surface->texture)
11308                                         break;
11309                                 texturesurfacelist[texturenumsurfaces++] = surface;
11310                         }
11311                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11312                                 continue;
11313                         // render the range of surfaces as depth
11314                         if (!setup)
11315                         {
11316                                 setup = true;
11317                                 GL_ColorMask(0,0,0,0);
11318                                 GL_Color(1,1,1,1);
11319                                 GL_DepthTest(true);
11320                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11321                                 GL_DepthMask(true);
11322 //                              R_Mesh_ResetTextureState();
11323                         }
11324                         RSurf_SetupDepthAndCulling();
11325                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11326                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11327                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11328                         RSurf_DrawBatch();
11329                 }
11330                 if (setup)
11331                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11332         }
11333
11334         for (i = 0;i < numsurfaces;i = j)
11335         {
11336                 j = i + 1;
11337                 surface = rsurface.modelsurfaces + surfacelist[i];
11338                 texture = surface->texture;
11339                 rsurface.texture = R_GetCurrentTexture(texture);
11340                 // scan ahead until we find a different texture
11341                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11342                 texturenumsurfaces = 0;
11343                 texturesurfacelist[texturenumsurfaces++] = surface;
11344                 if(FAKELIGHT_ENABLED)
11345                 {
11346                         rsurface.lightmaptexture = NULL;
11347                         rsurface.deluxemaptexture = NULL;
11348                         rsurface.uselightmaptexture = false;
11349                         for (;j < endsurface;j++)
11350                         {
11351                                 surface = rsurface.modelsurfaces + surfacelist[j];
11352                                 if (texture != surface->texture)
11353                                         break;
11354                                 texturesurfacelist[texturenumsurfaces++] = surface;
11355                         }
11356                 }
11357                 else
11358                 {
11359                         rsurface.lightmaptexture = surface->lightmaptexture;
11360                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11361                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11362                         for (;j < endsurface;j++)
11363                         {
11364                                 surface = rsurface.modelsurfaces + surfacelist[j];
11365                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11366                                         break;
11367                                 texturesurfacelist[texturenumsurfaces++] = surface;
11368                         }
11369                 }
11370                 // render the range of surfaces
11371                 if (ent == r_refdef.scene.worldentity)
11372                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11373                 else
11374                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11375         }
11376         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11377 }
11378
11379 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11380 {
11381         // transparent surfaces get pushed off into the transparent queue
11382         int surfacelistindex;
11383         const msurface_t *surface;
11384         vec3_t tempcenter, center;
11385         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11386         {
11387                 surface = texturesurfacelist[surfacelistindex];
11388                 if (r_transparent_sortsurfacesbynearest.integer)
11389                 {
11390                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11391                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11392                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11393                 }
11394                 else
11395                 {
11396                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11397                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11398                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11399                 }
11400                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11401                 if (rsurface.entity->transparent_offset) // transparent offset
11402                 {
11403                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11404                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11405                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11406                 }
11407                 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);
11408         }
11409 }
11410
11411 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11412 {
11413         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11414                 return;
11415         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11416                 return;
11417         RSurf_SetupDepthAndCulling();
11418         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11419         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11420         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11421         RSurf_DrawBatch();
11422 }
11423
11424 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11425 {
11426         CHECKGLERROR
11427         if (depthonly)
11428                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11429         else if (prepass)
11430         {
11431                 if (!rsurface.texture->currentnumlayers)
11432                         return;
11433                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11434                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11435                 else
11436                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11437         }
11438         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11439                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11440         else if (!rsurface.texture->currentnumlayers)
11441                 return;
11442         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11443         {
11444                 // in the deferred case, transparent surfaces were queued during prepass
11445                 if (!r_shadow_usingdeferredprepass)
11446                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11447         }
11448         else
11449         {
11450                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11451                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11452         }
11453         CHECKGLERROR
11454 }
11455
11456 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11457 {
11458         int i, j;
11459         texture_t *texture;
11460         R_FrameData_SetMark();
11461         // break the surface list down into batches by texture and use of lightmapping
11462         for (i = 0;i < numsurfaces;i = j)
11463         {
11464                 j = i + 1;
11465                 // texture is the base texture pointer, rsurface.texture is the
11466                 // current frame/skin the texture is directing us to use (for example
11467                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11468                 // use skin 1 instead)
11469                 texture = surfacelist[i]->texture;
11470                 rsurface.texture = R_GetCurrentTexture(texture);
11471                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11472                 {
11473                         // if this texture is not the kind we want, skip ahead to the next one
11474                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11475                                 ;
11476                         continue;
11477                 }
11478                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11479                 {
11480                         rsurface.lightmaptexture = NULL;
11481                         rsurface.deluxemaptexture = NULL;
11482                         rsurface.uselightmaptexture = false;
11483                         // simply scan ahead until we find a different texture or lightmap state
11484                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11485                                 ;
11486                 }
11487                 else
11488                 {
11489                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11490                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11491                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11492                         // simply scan ahead until we find a different texture or lightmap state
11493                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11494                                 ;
11495                 }
11496                 // render the range of surfaces
11497                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11498         }
11499         R_FrameData_ReturnToMark();
11500 }
11501
11502 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11503 {
11504         CHECKGLERROR
11505         if (depthonly)
11506                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11507         else if (prepass)
11508         {
11509                 if (!rsurface.texture->currentnumlayers)
11510                         return;
11511                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11512                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11513                 else
11514                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11515         }
11516         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11517                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11518         else if (!rsurface.texture->currentnumlayers)
11519                 return;
11520         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11521         {
11522                 // in the deferred case, transparent surfaces were queued during prepass
11523                 if (!r_shadow_usingdeferredprepass)
11524                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11525         }
11526         else
11527         {
11528                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11529                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11530         }
11531         CHECKGLERROR
11532 }
11533
11534 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11535 {
11536         int i, j;
11537         texture_t *texture;
11538         R_FrameData_SetMark();
11539         // break the surface list down into batches by texture and use of lightmapping
11540         for (i = 0;i < numsurfaces;i = j)
11541         {
11542                 j = i + 1;
11543                 // texture is the base texture pointer, rsurface.texture is the
11544                 // current frame/skin the texture is directing us to use (for example
11545                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11546                 // use skin 1 instead)
11547                 texture = surfacelist[i]->texture;
11548                 rsurface.texture = R_GetCurrentTexture(texture);
11549                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11550                 {
11551                         // if this texture is not the kind we want, skip ahead to the next one
11552                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11553                                 ;
11554                         continue;
11555                 }
11556                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11557                 {
11558                         rsurface.lightmaptexture = NULL;
11559                         rsurface.deluxemaptexture = NULL;
11560                         rsurface.uselightmaptexture = false;
11561                         // simply scan ahead until we find a different texture or lightmap state
11562                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11563                                 ;
11564                 }
11565                 else
11566                 {
11567                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11568                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11569                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11570                         // simply scan ahead until we find a different texture or lightmap state
11571                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11572                                 ;
11573                 }
11574                 // render the range of surfaces
11575                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11576         }
11577         R_FrameData_ReturnToMark();
11578 }
11579
11580 float locboxvertex3f[6*4*3] =
11581 {
11582         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11583         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11584         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11585         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11586         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11587         1,0,0, 0,0,0, 0,1,0, 1,1,0
11588 };
11589
11590 unsigned short locboxelements[6*2*3] =
11591 {
11592          0, 1, 2, 0, 2, 3,
11593          4, 5, 6, 4, 6, 7,
11594          8, 9,10, 8,10,11,
11595         12,13,14, 12,14,15,
11596         16,17,18, 16,18,19,
11597         20,21,22, 20,22,23
11598 };
11599
11600 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11601 {
11602         int i, j;
11603         cl_locnode_t *loc = (cl_locnode_t *)ent;
11604         vec3_t mins, size;
11605         float vertex3f[6*4*3];
11606         CHECKGLERROR
11607         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11608         GL_DepthMask(false);
11609         GL_DepthRange(0, 1);
11610         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11611         GL_DepthTest(true);
11612         GL_CullFace(GL_NONE);
11613         R_EntityMatrix(&identitymatrix);
11614
11615 //      R_Mesh_ResetTextureState();
11616
11617         i = surfacelist[0];
11618         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11619                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11620                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11621                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11622
11623         if (VectorCompare(loc->mins, loc->maxs))
11624         {
11625                 VectorSet(size, 2, 2, 2);
11626                 VectorMA(loc->mins, -0.5f, size, mins);
11627         }
11628         else
11629         {
11630                 VectorCopy(loc->mins, mins);
11631                 VectorSubtract(loc->maxs, loc->mins, size);
11632         }
11633
11634         for (i = 0;i < 6*4*3;)
11635                 for (j = 0;j < 3;j++, i++)
11636                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11637
11638         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11639         R_SetupShader_Generic_NoTexture(false, false);
11640         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11641 }
11642
11643 void R_DrawLocs(void)
11644 {
11645         int index;
11646         cl_locnode_t *loc, *nearestloc;
11647         vec3_t center;
11648         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11649         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11650         {
11651                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11652                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11653         }
11654 }
11655
11656 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11657 {
11658         if (decalsystem->decals)
11659                 Mem_Free(decalsystem->decals);
11660         memset(decalsystem, 0, sizeof(*decalsystem));
11661 }
11662
11663 static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, unsigned int decalsequence)
11664 {
11665         tridecal_t *decal;
11666         tridecal_t *decals;
11667         int i;
11668
11669         // expand or initialize the system
11670         if (decalsystem->maxdecals <= decalsystem->numdecals)
11671         {
11672                 decalsystem_t old = *decalsystem;
11673                 qboolean useshortelements;
11674                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11675                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11676                 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)));
11677                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11678                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11679                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11680                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11681                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11682                 if (decalsystem->numdecals)
11683                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11684                 if (old.decals)
11685                         Mem_Free(old.decals);
11686                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11687                         decalsystem->element3i[i] = i;
11688                 if (useshortelements)
11689                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11690                                 decalsystem->element3s[i] = i;
11691         }
11692
11693         // grab a decal and search for another free slot for the next one
11694         decals = decalsystem->decals;
11695         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11696         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11697                 ;
11698         decalsystem->freedecal = i;
11699         if (decalsystem->numdecals <= i)
11700                 decalsystem->numdecals = i + 1;
11701
11702         // initialize the decal
11703         decal->lived = 0;
11704         decal->triangleindex = triangleindex;
11705         decal->surfaceindex = surfaceindex;
11706         decal->decalsequence = decalsequence;
11707         decal->color4f[0][0] = c0[0];
11708         decal->color4f[0][1] = c0[1];
11709         decal->color4f[0][2] = c0[2];
11710         decal->color4f[0][3] = 1;
11711         decal->color4f[1][0] = c1[0];
11712         decal->color4f[1][1] = c1[1];
11713         decal->color4f[1][2] = c1[2];
11714         decal->color4f[1][3] = 1;
11715         decal->color4f[2][0] = c2[0];
11716         decal->color4f[2][1] = c2[1];
11717         decal->color4f[2][2] = c2[2];
11718         decal->color4f[2][3] = 1;
11719         decal->vertex3f[0][0] = v0[0];
11720         decal->vertex3f[0][1] = v0[1];
11721         decal->vertex3f[0][2] = v0[2];
11722         decal->vertex3f[1][0] = v1[0];
11723         decal->vertex3f[1][1] = v1[1];
11724         decal->vertex3f[1][2] = v1[2];
11725         decal->vertex3f[2][0] = v2[0];
11726         decal->vertex3f[2][1] = v2[1];
11727         decal->vertex3f[2][2] = v2[2];
11728         decal->texcoord2f[0][0] = t0[0];
11729         decal->texcoord2f[0][1] = t0[1];
11730         decal->texcoord2f[1][0] = t1[0];
11731         decal->texcoord2f[1][1] = t1[1];
11732         decal->texcoord2f[2][0] = t2[0];
11733         decal->texcoord2f[2][1] = t2[1];
11734         TriangleNormal(v0, v1, v2, decal->plane);
11735         VectorNormalize(decal->plane);
11736         decal->plane[3] = DotProduct(v0, decal->plane);
11737 }
11738
11739 extern cvar_t cl_decals_bias;
11740 extern cvar_t cl_decals_models;
11741 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11742 // baseparms, parms, temps
11743 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, unsigned int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
11744 {
11745         int cornerindex;
11746         int index;
11747         float v[9][3];
11748         const float *vertex3f;
11749         const float *normal3f;
11750         int numpoints;
11751         float points[2][9][3];
11752         float temp[3];
11753         float tc[9][2];
11754         float f;
11755         float c[9][4];
11756         const int *e;
11757
11758         e = rsurface.modelelement3i + 3*triangleindex;
11759
11760         vertex3f = rsurface.modelvertex3f;
11761         normal3f = rsurface.modelnormal3f;
11762
11763         if (normal3f)
11764         {
11765                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11766                 {
11767                         index = 3*e[cornerindex];
11768                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11769                 }
11770         }
11771         else
11772         {
11773                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11774                 {
11775                         index = 3*e[cornerindex];
11776                         VectorCopy(vertex3f + index, v[cornerindex]);
11777                 }
11778         }
11779
11780         // cull backfaces
11781         //TriangleNormal(v[0], v[1], v[2], normal);
11782         //if (DotProduct(normal, localnormal) < 0.0f)
11783         //      continue;
11784         // clip by each of the box planes formed from the projection matrix
11785         // if anything survives, we emit the decal
11786         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]);
11787         if (numpoints < 3)
11788                 return;
11789         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]);
11790         if (numpoints < 3)
11791                 return;
11792         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]);
11793         if (numpoints < 3)
11794                 return;
11795         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]);
11796         if (numpoints < 3)
11797                 return;
11798         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]);
11799         if (numpoints < 3)
11800                 return;
11801         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]);
11802         if (numpoints < 3)
11803                 return;
11804         // some part of the triangle survived, so we have to accept it...
11805         if (dynamic)
11806         {
11807                 // dynamic always uses the original triangle
11808                 numpoints = 3;
11809                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11810                 {
11811                         index = 3*e[cornerindex];
11812                         VectorCopy(vertex3f + index, v[cornerindex]);
11813                 }
11814         }
11815         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11816         {
11817                 // convert vertex positions to texcoords
11818                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11819                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11820                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11821                 // calculate distance fade from the projection origin
11822                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11823                 f = bound(0.0f, f, 1.0f);
11824                 c[cornerindex][0] = r * f;
11825                 c[cornerindex][1] = g * f;
11826                 c[cornerindex][2] = b * f;
11827                 c[cornerindex][3] = 1.0f;
11828                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11829         }
11830         if (dynamic)
11831                 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);
11832         else
11833                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11834                         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);
11835 }
11836 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, unsigned int decalsequence)
11837 {
11838         matrix4x4_t projection;
11839         decalsystem_t *decalsystem;
11840         qboolean dynamic;
11841         dp_model_t *model;
11842         const msurface_t *surface;
11843         const msurface_t *surfaces;
11844         const int *surfacelist;
11845         const texture_t *texture;
11846         int numtriangles;
11847         int numsurfacelist;
11848         int surfacelistindex;
11849         int surfaceindex;
11850         int triangleindex;
11851         float localorigin[3];
11852         float localnormal[3];
11853         float localmins[3];
11854         float localmaxs[3];
11855         float localsize;
11856         //float normal[3];
11857         float planes[6][4];
11858         float angles[3];
11859         bih_t *bih;
11860         int bih_triangles_count;
11861         int bih_triangles[256];
11862         int bih_surfaces[256];
11863
11864         decalsystem = &ent->decalsystem;
11865         model = ent->model;
11866         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11867         {
11868                 R_DecalSystem_Reset(&ent->decalsystem);
11869                 return;
11870         }
11871
11872         if (!model->brush.data_leafs && !cl_decals_models.integer)
11873         {
11874                 if (decalsystem->model)
11875                         R_DecalSystem_Reset(decalsystem);
11876                 return;
11877         }
11878
11879         if (decalsystem->model != model)
11880                 R_DecalSystem_Reset(decalsystem);
11881         decalsystem->model = model;
11882
11883         RSurf_ActiveModelEntity(ent, true, false, false);
11884
11885         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11886         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11887         VectorNormalize(localnormal);
11888         localsize = worldsize*rsurface.inversematrixscale;
11889         localmins[0] = localorigin[0] - localsize;
11890         localmins[1] = localorigin[1] - localsize;
11891         localmins[2] = localorigin[2] - localsize;
11892         localmaxs[0] = localorigin[0] + localsize;
11893         localmaxs[1] = localorigin[1] + localsize;
11894         localmaxs[2] = localorigin[2] + localsize;
11895
11896         //VectorCopy(localnormal, planes[4]);
11897         //VectorVectors(planes[4], planes[2], planes[0]);
11898         AnglesFromVectors(angles, localnormal, NULL, false);
11899         AngleVectors(angles, planes[0], planes[2], planes[4]);
11900         VectorNegate(planes[0], planes[1]);
11901         VectorNegate(planes[2], planes[3]);
11902         VectorNegate(planes[4], planes[5]);
11903         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11904         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11905         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11906         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11907         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11908         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11909
11910 #if 1
11911 // works
11912 {
11913         matrix4x4_t forwardprojection;
11914         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11915         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11916 }
11917 #else
11918 // broken
11919 {
11920         float projectionvector[4][3];
11921         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11922         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11923         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11924         projectionvector[0][0] = planes[0][0] * ilocalsize;
11925         projectionvector[0][1] = planes[1][0] * ilocalsize;
11926         projectionvector[0][2] = planes[2][0] * ilocalsize;
11927         projectionvector[1][0] = planes[0][1] * ilocalsize;
11928         projectionvector[1][1] = planes[1][1] * ilocalsize;
11929         projectionvector[1][2] = planes[2][1] * ilocalsize;
11930         projectionvector[2][0] = planes[0][2] * ilocalsize;
11931         projectionvector[2][1] = planes[1][2] * ilocalsize;
11932         projectionvector[2][2] = planes[2][2] * ilocalsize;
11933         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11934         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11935         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11936         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11937 }
11938 #endif
11939
11940         dynamic = model->surfmesh.isanimated;
11941         numsurfacelist = model->nummodelsurfaces;
11942         surfacelist = model->sortedmodelsurfaces;
11943         surfaces = model->data_surfaces;
11944
11945         bih = NULL;
11946         bih_triangles_count = -1;
11947         if(!dynamic)
11948         {
11949                 if(model->render_bih.numleafs)
11950                         bih = &model->render_bih;
11951                 else if(model->collision_bih.numleafs)
11952                         bih = &model->collision_bih;
11953         }
11954         if(bih)
11955                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11956         if(bih_triangles_count == 0)
11957                 return;
11958         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11959                 return;
11960         if(bih_triangles_count > 0)
11961         {
11962                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11963                 {
11964                         surfaceindex = bih_surfaces[triangleindex];
11965                         surface = surfaces + surfaceindex;
11966                         texture = surface->texture;
11967                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11968                                 continue;
11969                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11970                                 continue;
11971                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11972                 }
11973         }
11974         else
11975         {
11976                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11977                 {
11978                         surfaceindex = surfacelist[surfacelistindex];
11979                         surface = surfaces + surfaceindex;
11980                         // check cull box first because it rejects more than any other check
11981                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11982                                 continue;
11983                         // skip transparent surfaces
11984                         texture = surface->texture;
11985                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11986                                 continue;
11987                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11988                                 continue;
11989                         numtriangles = surface->num_triangles;
11990                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11991                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11992                 }
11993         }
11994 }
11995
11996 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11997 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, unsigned int decalsequence)
11998 {
11999         int renderentityindex;
12000         float worldmins[3];
12001         float worldmaxs[3];
12002         entity_render_t *ent;
12003
12004         if (!cl_decals_newsystem.integer)
12005                 return;
12006
12007         worldmins[0] = worldorigin[0] - worldsize;
12008         worldmins[1] = worldorigin[1] - worldsize;
12009         worldmins[2] = worldorigin[2] - worldsize;
12010         worldmaxs[0] = worldorigin[0] + worldsize;
12011         worldmaxs[1] = worldorigin[1] + worldsize;
12012         worldmaxs[2] = worldorigin[2] + worldsize;
12013
12014         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12015
12016         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
12017         {
12018                 ent = r_refdef.scene.entities[renderentityindex];
12019                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
12020                         continue;
12021
12022                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
12023         }
12024 }
12025
12026 typedef struct r_decalsystem_splatqueue_s
12027 {
12028         vec3_t worldorigin;
12029         vec3_t worldnormal;
12030         float color[4];
12031         float tcrange[4];
12032         float worldsize;
12033         unsigned int decalsequence;
12034 }
12035 r_decalsystem_splatqueue_t;
12036
12037 int r_decalsystem_numqueued = 0;
12038 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12039
12040 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)
12041 {
12042         r_decalsystem_splatqueue_t *queue;
12043
12044         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12045                 return;
12046
12047         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12048         VectorCopy(worldorigin, queue->worldorigin);
12049         VectorCopy(worldnormal, queue->worldnormal);
12050         Vector4Set(queue->color, r, g, b, a);
12051         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12052         queue->worldsize = worldsize;
12053         queue->decalsequence = cl.decalsequence++;
12054 }
12055
12056 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12057 {
12058         int i;
12059         r_decalsystem_splatqueue_t *queue;
12060
12061         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12062                 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);
12063         r_decalsystem_numqueued = 0;
12064 }
12065
12066 extern cvar_t cl_decals_max;
12067 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12068 {
12069         int i;
12070         decalsystem_t *decalsystem = &ent->decalsystem;
12071         int numdecals;
12072         unsigned int killsequence;
12073         tridecal_t *decal;
12074         float frametime;
12075         float lifetime;
12076
12077         if (!decalsystem->numdecals)
12078                 return;
12079
12080         if (r_showsurfaces.integer)
12081                 return;
12082
12083         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12084         {
12085                 R_DecalSystem_Reset(decalsystem);
12086                 return;
12087         }
12088
12089         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12090         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12091
12092         if (decalsystem->lastupdatetime)
12093                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12094         else
12095                 frametime = 0;
12096         decalsystem->lastupdatetime = r_refdef.scene.time;
12097         numdecals = decalsystem->numdecals;
12098
12099         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12100         {
12101                 if (decal->color4f[0][3])
12102                 {
12103                         decal->lived += frametime;
12104                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12105                         {
12106                                 memset(decal, 0, sizeof(*decal));
12107                                 if (decalsystem->freedecal > i)
12108                                         decalsystem->freedecal = i;
12109                         }
12110                 }
12111         }
12112         decal = decalsystem->decals;
12113         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12114                 numdecals--;
12115
12116         // collapse the array by shuffling the tail decals into the gaps
12117         for (;;)
12118         {
12119                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12120                         decalsystem->freedecal++;
12121                 if (decalsystem->freedecal == numdecals)
12122                         break;
12123                 decal[decalsystem->freedecal] = decal[--numdecals];
12124         }
12125
12126         decalsystem->numdecals = numdecals;
12127
12128         if (numdecals <= 0)
12129         {
12130                 // if there are no decals left, reset decalsystem
12131                 R_DecalSystem_Reset(decalsystem);
12132         }
12133 }
12134
12135 extern skinframe_t *decalskinframe;
12136 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12137 {
12138         int i;
12139         decalsystem_t *decalsystem = &ent->decalsystem;
12140         int numdecals;
12141         tridecal_t *decal;
12142         float faderate;
12143         float alpha;
12144         float *v3f;
12145         float *c4f;
12146         float *t2f;
12147         const int *e;
12148         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12149         int numtris = 0;
12150
12151         numdecals = decalsystem->numdecals;
12152         if (!numdecals)
12153                 return;
12154
12155         if (r_showsurfaces.integer)
12156                 return;
12157
12158         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12159         {
12160                 R_DecalSystem_Reset(decalsystem);
12161                 return;
12162         }
12163
12164         // if the model is static it doesn't matter what value we give for
12165         // wantnormals and wanttangents, so this logic uses only rules applicable
12166         // to a model, knowing that they are meaningless otherwise
12167         if (ent == r_refdef.scene.worldentity)
12168                 RSurf_ActiveWorldEntity();
12169         else
12170                 RSurf_ActiveModelEntity(ent, false, false, false);
12171
12172         decalsystem->lastupdatetime = r_refdef.scene.time;
12173
12174         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12175
12176         // update vertex positions for animated models
12177         v3f = decalsystem->vertex3f;
12178         c4f = decalsystem->color4f;
12179         t2f = decalsystem->texcoord2f;
12180         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12181         {
12182                 if (!decal->color4f[0][3])
12183                         continue;
12184
12185                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12186                         continue;
12187
12188                 // skip backfaces
12189                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12190                         continue;
12191
12192                 // update color values for fading decals
12193                 if (decal->lived >= cl_decals_time.value)
12194                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12195                 else
12196                         alpha = 1.0f;
12197
12198                 c4f[ 0] = decal->color4f[0][0] * alpha;
12199                 c4f[ 1] = decal->color4f[0][1] * alpha;
12200                 c4f[ 2] = decal->color4f[0][2] * alpha;
12201                 c4f[ 3] = 1;
12202                 c4f[ 4] = decal->color4f[1][0] * alpha;
12203                 c4f[ 5] = decal->color4f[1][1] * alpha;
12204                 c4f[ 6] = decal->color4f[1][2] * alpha;
12205                 c4f[ 7] = 1;
12206                 c4f[ 8] = decal->color4f[2][0] * alpha;
12207                 c4f[ 9] = decal->color4f[2][1] * alpha;
12208                 c4f[10] = decal->color4f[2][2] * alpha;
12209                 c4f[11] = 1;
12210
12211                 t2f[0] = decal->texcoord2f[0][0];
12212                 t2f[1] = decal->texcoord2f[0][1];
12213                 t2f[2] = decal->texcoord2f[1][0];
12214                 t2f[3] = decal->texcoord2f[1][1];
12215                 t2f[4] = decal->texcoord2f[2][0];
12216                 t2f[5] = decal->texcoord2f[2][1];
12217
12218                 // update vertex positions for animated models
12219                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12220                 {
12221                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12222                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12223                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12224                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12225                 }
12226                 else
12227                 {
12228                         VectorCopy(decal->vertex3f[0], v3f);
12229                         VectorCopy(decal->vertex3f[1], v3f + 3);
12230                         VectorCopy(decal->vertex3f[2], v3f + 6);
12231                 }
12232
12233                 if (r_refdef.fogenabled)
12234                 {
12235                         alpha = RSurf_FogVertex(v3f);
12236                         VectorScale(c4f, alpha, c4f);
12237                         alpha = RSurf_FogVertex(v3f + 3);
12238                         VectorScale(c4f + 4, alpha, c4f + 4);
12239                         alpha = RSurf_FogVertex(v3f + 6);
12240                         VectorScale(c4f + 8, alpha, c4f + 8);
12241                 }
12242
12243                 v3f += 9;
12244                 c4f += 12;
12245                 t2f += 6;
12246                 numtris++;
12247         }
12248
12249         if (numtris > 0)
12250         {
12251                 r_refdef.stats[r_stat_drawndecals] += numtris;
12252
12253                 // now render the decals all at once
12254                 // (this assumes they all use one particle font texture!)
12255                 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);
12256 //              R_Mesh_ResetTextureState();
12257                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12258                 GL_DepthMask(false);
12259                 GL_DepthRange(0, 1);
12260                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12261                 GL_DepthTest(true);
12262                 GL_CullFace(GL_NONE);
12263                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12264                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12265                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12266         }
12267 }
12268
12269 static void R_DrawModelDecals(void)
12270 {
12271         int i, numdecals;
12272
12273         // fade faster when there are too many decals
12274         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12275         for (i = 0;i < r_refdef.scene.numentities;i++)
12276                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12277
12278         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12279         for (i = 0;i < r_refdef.scene.numentities;i++)
12280                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12281                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12282
12283         R_DecalSystem_ApplySplatEntitiesQueue();
12284
12285         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12286         for (i = 0;i < r_refdef.scene.numentities;i++)
12287                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12288
12289         r_refdef.stats[r_stat_totaldecals] += numdecals;
12290
12291         if (r_showsurfaces.integer)
12292                 return;
12293
12294         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12295
12296         for (i = 0;i < r_refdef.scene.numentities;i++)
12297         {
12298                 if (!r_refdef.viewcache.entityvisible[i])
12299                         continue;
12300                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12301                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12302         }
12303 }
12304
12305 extern cvar_t mod_collision_bih;
12306 static void R_DrawDebugModel(void)
12307 {
12308         entity_render_t *ent = rsurface.entity;
12309         int i, j, flagsmask;
12310         const msurface_t *surface;
12311         dp_model_t *model = ent->model;
12312
12313         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12314                 return;
12315
12316         if (r_showoverdraw.value > 0)
12317         {
12318                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12319                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12320                 R_SetupShader_Generic_NoTexture(false, false);
12321                 GL_DepthTest(false);
12322                 GL_DepthMask(false);
12323                 GL_DepthRange(0, 1);
12324                 GL_BlendFunc(GL_ONE, GL_ONE);
12325                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12326                 {
12327                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12328                                 continue;
12329                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12330                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12331                         {
12332                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12333                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12334                                 if (!rsurface.texture->currentlayers->depthmask)
12335                                         GL_Color(c, 0, 0, 1.0f);
12336                                 else if (ent == r_refdef.scene.worldentity)
12337                                         GL_Color(c, c, c, 1.0f);
12338                                 else
12339                                         GL_Color(0, c, 0, 1.0f);
12340                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12341                                 RSurf_DrawBatch();
12342                         }
12343                 }
12344                 rsurface.texture = NULL;
12345         }
12346
12347         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12348
12349 //      R_Mesh_ResetTextureState();
12350         R_SetupShader_Generic_NoTexture(false, false);
12351         GL_DepthRange(0, 1);
12352         GL_DepthTest(!r_showdisabledepthtest.integer);
12353         GL_DepthMask(false);
12354         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12355
12356         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12357         {
12358                 int triangleindex;
12359                 int bihleafindex;
12360                 qboolean cullbox = false;
12361                 const q3mbrush_t *brush;
12362                 const bih_t *bih = &model->collision_bih;
12363                 const bih_leaf_t *bihleaf;
12364                 float vertex3f[3][3];
12365                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12366                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12367                 {
12368                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12369                                 continue;
12370                         switch (bihleaf->type)
12371                         {
12372                         case BIH_BRUSH:
12373                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12374                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12375                                 {
12376                                         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);
12377                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12378                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12379                                 }
12380                                 break;
12381                         case BIH_COLLISIONTRIANGLE:
12382                                 triangleindex = bihleaf->itemindex;
12383                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12384                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12385                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12386                                 GL_Color((bihleafindex & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 5) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, ((bihleafindex >> 10) & 31) * (1.0f / 32.0f) * r_refdef.view.colorscale, r_showcollisionbrushes.value);
12387                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12388                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12389                                 break;
12390                         case BIH_RENDERTRIANGLE:
12391                                 triangleindex = bihleaf->itemindex;
12392                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12393                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12394                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12395                                 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);
12396                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12397                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12398                                 break;
12399                         }
12400                 }
12401         }
12402
12403         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12404
12405 #ifndef USE_GLES2
12406         if (r_showtris.integer && qglPolygonMode)
12407         {
12408                 if (r_showdisabledepthtest.integer)
12409                 {
12410                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12411                         GL_DepthMask(false);
12412                 }
12413                 else
12414                 {
12415                         GL_BlendFunc(GL_ONE, GL_ZERO);
12416                         GL_DepthMask(true);
12417                 }
12418                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12419                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12420                 {
12421                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12422                                 continue;
12423                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12424                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12425                         {
12426                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12427                                 if (!rsurface.texture->currentlayers->depthmask)
12428                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12429                                 else if (ent == r_refdef.scene.worldentity)
12430                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12431                                 else
12432                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12433                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12434                                 RSurf_DrawBatch();
12435                         }
12436                 }
12437                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12438                 rsurface.texture = NULL;
12439         }
12440
12441         if (r_shownormals.value != 0 && qglBegin)
12442         {
12443                 int l, k;
12444                 vec3_t v;
12445                 if (r_showdisabledepthtest.integer)
12446                 {
12447                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12448                         GL_DepthMask(false);
12449                 }
12450                 else
12451                 {
12452                         GL_BlendFunc(GL_ONE, GL_ZERO);
12453                         GL_DepthMask(true);
12454                 }
12455                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12456                 {
12457                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12458                                 continue;
12459                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12460                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12461                         {
12462                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12463                                 qglBegin(GL_LINES);
12464                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12465                                 {
12466                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12467                                         {
12468                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12469                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12470                                                 qglVertex3f(v[0], v[1], v[2]);
12471                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12472                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12473                                                 qglVertex3f(v[0], v[1], v[2]);
12474                                         }
12475                                 }
12476                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12477                                 {
12478                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12479                                         {
12480                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12481                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12482                                                 qglVertex3f(v[0], v[1], v[2]);
12483                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12484                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12485                                                 qglVertex3f(v[0], v[1], v[2]);
12486                                         }
12487                                 }
12488                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12489                                 {
12490                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12491                                         {
12492                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12493                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12494                                                 qglVertex3f(v[0], v[1], v[2]);
12495                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12496                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12497                                                 qglVertex3f(v[0], v[1], v[2]);
12498                                         }
12499                                 }
12500                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12501                                 {
12502                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12503                                         {
12504                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12505                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12506                                                 qglVertex3f(v[0], v[1], v[2]);
12507                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12508                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12509                                                 qglVertex3f(v[0], v[1], v[2]);
12510                                         }
12511                                 }
12512                                 qglEnd();
12513                                 CHECKGLERROR
12514                         }
12515                 }
12516                 rsurface.texture = NULL;
12517         }
12518 #endif
12519 }
12520
12521 int r_maxsurfacelist = 0;
12522 const msurface_t **r_surfacelist = NULL;
12523 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12524 {
12525         int i, j, endj, flagsmask;
12526         dp_model_t *model = r_refdef.scene.worldmodel;
12527         msurface_t *surfaces;
12528         unsigned char *update;
12529         int numsurfacelist = 0;
12530         if (model == NULL)
12531                 return;
12532
12533         if (r_maxsurfacelist < model->num_surfaces)
12534         {
12535                 r_maxsurfacelist = model->num_surfaces;
12536                 if (r_surfacelist)
12537                         Mem_Free((msurface_t**)r_surfacelist);
12538                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12539         }
12540
12541         RSurf_ActiveWorldEntity();
12542
12543         surfaces = model->data_surfaces;
12544         update = model->brushq1.lightmapupdateflags;
12545
12546         // update light styles on this submodel
12547         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12548         {
12549                 model_brush_lightstyleinfo_t *style;
12550                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12551                 {
12552                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12553                         {
12554                                 int *list = style->surfacelist;
12555                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12556                                 for (j = 0;j < style->numsurfaces;j++)
12557                                         update[list[j]] = true;
12558                         }
12559                 }
12560         }
12561
12562         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12563
12564         if (debug)
12565         {
12566                 R_DrawDebugModel();
12567                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12568                 return;
12569         }
12570
12571         rsurface.lightmaptexture = NULL;
12572         rsurface.deluxemaptexture = NULL;
12573         rsurface.uselightmaptexture = false;
12574         rsurface.texture = NULL;
12575         rsurface.rtlight = NULL;
12576         numsurfacelist = 0;
12577         // add visible surfaces to draw list
12578         for (i = 0;i < model->nummodelsurfaces;i++)
12579         {
12580                 j = model->sortedmodelsurfaces[i];
12581                 if (r_refdef.viewcache.world_surfacevisible[j])
12582                         r_surfacelist[numsurfacelist++] = surfaces + j;
12583         }
12584         // update lightmaps if needed
12585         if (model->brushq1.firstrender)
12586         {
12587                 model->brushq1.firstrender = false;
12588                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12589                         if (update[j])
12590                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12591         }
12592         else if (update)
12593         {
12594                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12595                         if (r_refdef.viewcache.world_surfacevisible[j])
12596                                 if (update[j])
12597                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12598         }
12599         // don't do anything if there were no surfaces
12600         if (!numsurfacelist)
12601         {
12602                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12603                 return;
12604         }
12605         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12606
12607         // add to stats if desired
12608         if (r_speeds.integer && !skysurfaces && !depthonly)
12609         {
12610                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12611                 for (j = 0;j < numsurfacelist;j++)
12612                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12613         }
12614
12615         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12616 }
12617
12618 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12619 {
12620         int i, j, endj, flagsmask;
12621         dp_model_t *model = ent->model;
12622         msurface_t *surfaces;
12623         unsigned char *update;
12624         int numsurfacelist = 0;
12625         if (model == NULL)
12626                 return;
12627
12628         if (r_maxsurfacelist < model->num_surfaces)
12629         {
12630                 r_maxsurfacelist = model->num_surfaces;
12631                 if (r_surfacelist)
12632                         Mem_Free((msurface_t **)r_surfacelist);
12633                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12634         }
12635
12636         // if the model is static it doesn't matter what value we give for
12637         // wantnormals and wanttangents, so this logic uses only rules applicable
12638         // to a model, knowing that they are meaningless otherwise
12639         if (ent == r_refdef.scene.worldentity)
12640                 RSurf_ActiveWorldEntity();
12641         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12642                 RSurf_ActiveModelEntity(ent, false, false, false);
12643         else if (prepass)
12644                 RSurf_ActiveModelEntity(ent, true, true, true);
12645         else if (depthonly)
12646         {
12647                 switch (vid.renderpath)
12648                 {
12649                 case RENDERPATH_GL20:
12650                 case RENDERPATH_D3D9:
12651                 case RENDERPATH_D3D10:
12652                 case RENDERPATH_D3D11:
12653                 case RENDERPATH_SOFT:
12654                 case RENDERPATH_GLES2:
12655                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12656                         break;
12657                 case RENDERPATH_GL11:
12658                 case RENDERPATH_GL13:
12659                 case RENDERPATH_GLES1:
12660                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12661                         break;
12662                 }
12663         }
12664         else
12665         {
12666                 switch (vid.renderpath)
12667                 {
12668                 case RENDERPATH_GL20:
12669                 case RENDERPATH_D3D9:
12670                 case RENDERPATH_D3D10:
12671                 case RENDERPATH_D3D11:
12672                 case RENDERPATH_SOFT:
12673                 case RENDERPATH_GLES2:
12674                         RSurf_ActiveModelEntity(ent, true, true, false);
12675                         break;
12676                 case RENDERPATH_GL11:
12677                 case RENDERPATH_GL13:
12678                 case RENDERPATH_GLES1:
12679                         RSurf_ActiveModelEntity(ent, true, false, false);
12680                         break;
12681                 }
12682         }
12683
12684         surfaces = model->data_surfaces;
12685         update = model->brushq1.lightmapupdateflags;
12686
12687         // update light styles
12688         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12689         {
12690                 model_brush_lightstyleinfo_t *style;
12691                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12692                 {
12693                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12694                         {
12695                                 int *list = style->surfacelist;
12696                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12697                                 for (j = 0;j < style->numsurfaces;j++)
12698                                         update[list[j]] = true;
12699                         }
12700                 }
12701         }
12702
12703         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12704
12705         if (debug)
12706         {
12707                 R_DrawDebugModel();
12708                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12709                 return;
12710         }
12711
12712         rsurface.lightmaptexture = NULL;
12713         rsurface.deluxemaptexture = NULL;
12714         rsurface.uselightmaptexture = false;
12715         rsurface.texture = NULL;
12716         rsurface.rtlight = NULL;
12717         numsurfacelist = 0;
12718         // add visible surfaces to draw list
12719         for (i = 0;i < model->nummodelsurfaces;i++)
12720                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12721         // don't do anything if there were no surfaces
12722         if (!numsurfacelist)
12723         {
12724                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12725                 return;
12726         }
12727         // update lightmaps if needed
12728         if (update)
12729         {
12730                 int updated = 0;
12731                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12732                 {
12733                         if (update[j])
12734                         {
12735                                 updated++;
12736                                 R_BuildLightMap(ent, surfaces + j);
12737                         }
12738                 }
12739         }
12740
12741         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12742
12743         // add to stats if desired
12744         if (r_speeds.integer && !skysurfaces && !depthonly)
12745         {
12746                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12747                 for (j = 0;j < numsurfacelist;j++)
12748                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12749         }
12750
12751         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12752 }
12753
12754 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12755 {
12756         static texture_t texture;
12757         static msurface_t surface;
12758         const msurface_t *surfacelist = &surface;
12759
12760         // fake enough texture and surface state to render this geometry
12761
12762         texture.update_lastrenderframe = -1; // regenerate this texture
12763         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12764         texture.basealpha = 1.0f;
12765         texture.currentskinframe = skinframe;
12766         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12767         texture.offsetmapping = OFFSETMAPPING_OFF;
12768         texture.offsetscale = 1;
12769         texture.specularscalemod = 1;
12770         texture.specularpowermod = 1;
12771         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12772         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12773         // JUST GREP FOR "specularscalemod = 1".
12774
12775         surface.texture = &texture;
12776         surface.num_triangles = numtriangles;
12777         surface.num_firsttriangle = firsttriangle;
12778         surface.num_vertices = numvertices;
12779         surface.num_firstvertex = firstvertex;
12780
12781         // now render it
12782         rsurface.texture = R_GetCurrentTexture(surface.texture);
12783         rsurface.lightmaptexture = NULL;
12784         rsurface.deluxemaptexture = NULL;
12785         rsurface.uselightmaptexture = false;
12786         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12787 }
12788
12789 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)
12790 {
12791         static msurface_t surface;
12792         const msurface_t *surfacelist = &surface;
12793
12794         // fake enough texture and surface state to render this geometry
12795         surface.texture = texture;
12796         surface.num_triangles = numtriangles;
12797         surface.num_firsttriangle = firsttriangle;
12798         surface.num_vertices = numvertices;
12799         surface.num_firstvertex = firstvertex;
12800
12801         // now render it
12802         rsurface.texture = R_GetCurrentTexture(surface.texture);
12803         rsurface.lightmaptexture = NULL;
12804         rsurface.deluxemaptexture = NULL;
12805         rsurface.uselightmaptexture = false;
12806         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12807 }