]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
f69ac7b0d1c122443e9a30c7bfe9cc0b621b39b1
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47 static qboolean r_gpuskeletal;
48
49 //
50 // screen size info
51 //
52 r_refdef_t r_refdef;
53
54 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
55 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended - NOTE: bad performance on multi-gpu!"};
56 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
57 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
58 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
59 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
60 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
61 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
62 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
63 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
64 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
65 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
66
67 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
68 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
69 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
70 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
71 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
72
73 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
74 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
75 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
76 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
77 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
78 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
79 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
80 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
81 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
82 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
83 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
84 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
85 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
86 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
87 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
88 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
89 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
90 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
91 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
92 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
93 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
94 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
95 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
96 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
97 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
98 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
99 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
100 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
101 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
102 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
103 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
104 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
105 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
106 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
107 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
108
109 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
110 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
111 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
112
113 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
114 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
115 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
116 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
117 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
118 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
119 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
120 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
121 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
122 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
123 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
124 cvar_t r_shadows_shadowmapbias = {CVAR_SAVE, "r_shadows_shadowmapbias", "-1", "sets shadowmap bias for fake shadows. -1 sets the value of r_shadow_shadowmapping_bias. Needs shadowmapping ON."};
125 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
126 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
127 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
128 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
130 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
131 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
132 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
133 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
134 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
135 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
136 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
137 cvar_t r_celshading = {CVAR_SAVE, "r_celshading", "0", "cartoon-style light shading (OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
138 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred; OpenGL 2.x only)"}; // FIXME remove OpenGL 2.x only once implemented for DX9
139
140 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
141 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
142 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
143 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
144 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
145 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
146 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
147 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
148
149 cvar_t r_texture_dds_load = {CVAR_SAVE, "r_texture_dds_load", "0", "load compressed dds/filename.dds texture instead of filename.tga, if the file exists (requires driver support)"};
150 cvar_t r_texture_dds_save = {CVAR_SAVE, "r_texture_dds_save", "0", "save compressed dds/filename.dds texture when filename.tga is loaded, so that it can be loaded instead next time"};
151
152 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
153 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
154 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
155
156 cvar_t r_usedepthtextures = {CVAR_SAVE, "r_usedepthtextures", "1", "use depth texture instead of depth renderbuffer where possible, uses less video memory but may render slower (or faster) depending on hardware"};
157 cvar_t r_viewfbo = {CVAR_SAVE, "r_viewfbo", "0", "enables use of an 8bit (1) or 16bit (2) or 32bit (3) per component float framebuffer render, which may be at a different resolution than the video mode"};
158 cvar_t r_viewscale = {CVAR_SAVE, "r_viewscale", "1", "scaling factor for resolution of the fbo rendering method, must be > 0, can be above 1 for a costly antialiasing behavior, typical values are 0.5 for 1/4th as many pixels rendered, or 1 for normal rendering"};
159 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
160 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
161 cvar_t r_viewscale_fpsscaling_multiply = {CVAR_SAVE, "r_viewscale_fpsscaling_multiply", "5", "adjust quality up or down by the frametime difference from 1.0/target, multiplied by this factor"};
162 cvar_t r_viewscale_fpsscaling_stepsize = {CVAR_SAVE, "r_viewscale_fpsscaling_stepsize", "0.01", "smallest adjustment to hit the target framerate (this value prevents minute oscillations)"};
163 cvar_t r_viewscale_fpsscaling_stepmax = {CVAR_SAVE, "r_viewscale_fpsscaling_stepmax", "1.00", "largest adjustment to hit the target framerate (this value prevents wild overshooting of the estimate)"};
164 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
165
166 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
167 cvar_t r_glsl_deluxemapping = {CVAR_SAVE, "r_glsl_deluxemapping", "1", "use per pixel lighting on deluxemap-compiled q3bsp maps (or a value of 2 forces deluxemap shading even without deluxemaps)"};
168 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
169 cvar_t r_glsl_offsetmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_steps", "2", "offset mapping steps (note: too high values may be not supported by your GPU)"};
170 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
171 cvar_t r_glsl_offsetmapping_reliefmapping_steps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_steps", "10", "relief mapping steps (note: too high values may be not supported by your GPU)"};
172 cvar_t r_glsl_offsetmapping_reliefmapping_refinesteps = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping_refinesteps", "5", "relief mapping refine steps (these are a binary search executed as the last step as given by r_glsl_offsetmapping_reliefmapping_steps)"};
173 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
174 cvar_t r_glsl_offsetmapping_lod = {CVAR_SAVE, "r_glsl_offsetmapping_lod", "0", "apply distance-based level-of-detail correction to number of offsetmappig steps, effectively making it render faster on large open-area maps"};
175 cvar_t r_glsl_offsetmapping_lod_distance = {CVAR_SAVE, "r_glsl_offsetmapping_lod_distance", "32", "first LOD level distance, second level (-50% steps) is 2x of this, third (33%) - 3x etc."};
176 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
177 cvar_t r_glsl_postprocess_uservec1 = {CVAR_SAVE, "r_glsl_postprocess_uservec1", "0 0 0 0", "a 4-component vector to pass as uservec1 to the postprocessing shader (only useful if default.glsl has been customized)"};
178 cvar_t r_glsl_postprocess_uservec2 = {CVAR_SAVE, "r_glsl_postprocess_uservec2", "0 0 0 0", "a 4-component vector to pass as uservec2 to the postprocessing shader (only useful if default.glsl has been customized)"};
179 cvar_t r_glsl_postprocess_uservec3 = {CVAR_SAVE, "r_glsl_postprocess_uservec3", "0 0 0 0", "a 4-component vector to pass as uservec3 to the postprocessing shader (only useful if default.glsl has been customized)"};
180 cvar_t r_glsl_postprocess_uservec4 = {CVAR_SAVE, "r_glsl_postprocess_uservec4", "0 0 0 0", "a 4-component vector to pass as uservec4 to the postprocessing shader (only useful if default.glsl has been customized)"};
181 cvar_t r_glsl_postprocess_uservec1_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec1_enable", "1", "enables postprocessing uservec1 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
182 cvar_t r_glsl_postprocess_uservec2_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec2_enable", "1", "enables postprocessing uservec2 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
183 cvar_t r_glsl_postprocess_uservec3_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec3_enable", "1", "enables postprocessing uservec3 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
184 cvar_t r_glsl_postprocess_uservec4_enable = {CVAR_SAVE, "r_glsl_postprocess_uservec4_enable", "1", "enables postprocessing uservec4 usage, creates USERVEC1 define (only useful if default.glsl has been customized)"};
185
186 cvar_t r_water = {CVAR_SAVE, "r_water", "0", "whether to use reflections and refraction on water surfaces (note: r_wateralpha must be set below 1)"};
187 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
188 cvar_t r_water_resolutionmultiplier = {CVAR_SAVE, "r_water_resolutionmultiplier", "0.5", "multiplier for screen resolution when rendering refracted/reflected scenes, 1 is full quality, lower values are faster"};
189 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
190 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
191 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
192 cvar_t r_water_lowquality = {0, "r_water_lowquality", "0", "special option to accelerate water rendering, 1 disables shadows and particles, 2 disables all dynamic lights"};
193 cvar_t r_water_hideplayer = {CVAR_SAVE, "r_water_hideplayer", "0", "if set to 1 then player will be hidden in refraction views, if set to 2 then player will also be hidden in reflection views, player is always visible in camera views"};
194 cvar_t r_water_fbo = {CVAR_SAVE, "r_water_fbo", "1", "enables use of render to texture for water effects, otherwise copy to texture is used (slower)"};
195
196 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
197 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
198 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
199 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
200
201 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
202 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
203
204 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
205 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
206 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
207 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
208 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
209 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
210
211 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
212 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
213 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
214 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
215 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
217 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
218 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
219 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
220 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
221
222 cvar_t r_smoothnormals_areaweighting = {0, "r_smoothnormals_areaweighting", "1", "uses significantly faster (and supposedly higher quality) area-weighted vertex normals and tangent vectors rather than summing normalized triangle normals and tangents"};
223
224 cvar_t developer_texturelogging = {0, "developer_texturelogging", "0", "produces a textures.log file containing names of skins and map textures the engine tried to load"};
225
226 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
227
228 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
229
230 cvar_t r_batch_multidraw = {CVAR_SAVE, "r_batch_multidraw", "1", "issue multiple glDrawElements calls when rendering a batch of surfaces with the same texture (otherwise the index data is copied to make it one draw)"};
231 cvar_t r_batch_multidraw_mintriangles = {CVAR_SAVE, "r_batch_multidraw_mintriangles", "0", "minimum number of triangles to activate multidraw path (copying small groups of triangles may be faster)"};
232 cvar_t r_batch_debugdynamicvertexpath = {CVAR_SAVE, "r_batch_debugdynamicvertexpath", "0", "force the dynamic batching code path for debugging purposes"};
233 cvar_t r_batch_dynamicbuffer = {CVAR_SAVE, "r_batch_dynamicbuffer", "0", "use vertex/index buffers for drawing dynamic and copytriangles batches"};
234
235 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
236 cvar_t r_glsl_saturation_redcompensate = {CVAR_SAVE, "r_glsl_saturation_redcompensate", "0", "a 'vampire sight' addition to desaturation effect, does compensation for red color, r_glsl_restart is required"};
237
238 cvar_t r_glsl_vertextextureblend_usebothalphas = {CVAR_SAVE, "r_glsl_vertextextureblend_usebothalphas", "0", "use both alpha layers on vertex blended surfaces, each alpha layer sets amount of 'blend leak' on another layer, requires mod_q3shader_force_terrain_alphaflag on."};
239
240 cvar_t r_framedatasize = {CVAR_SAVE, "r_framedatasize", "0.5", "size of renderer data cache used during one frame (for skeletal animation caching, light processing, etc)"};
241 cvar_t r_buffermegs[R_BUFFERDATA_COUNT] =
242 {
243         {CVAR_SAVE, "r_buffermegs_vertex", "4", "vertex buffer size for one frame"},
244         {CVAR_SAVE, "r_buffermegs_index16", "1", "index buffer size for one frame (16bit indices)"},
245         {CVAR_SAVE, "r_buffermegs_index32", "1", "index buffer size for one frame (32bit indices)"},
246         {CVAR_SAVE, "r_buffermegs_uniform", "0.25", "uniform buffer size for one frame"},
247 };
248
249 extern cvar_t v_glslgamma;
250 extern cvar_t v_glslgamma_2d;
251
252 extern qboolean v_flipped_state;
253
254 r_framebufferstate_t r_fb;
255
256 /// shadow volume bsp struct with automatically growing nodes buffer
257 svbsp_t r_svbsp;
258
259 int r_uniformbufferalignment = 32; // dynamically updated to match GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
260
261 rtexture_t *r_texture_blanknormalmap;
262 rtexture_t *r_texture_white;
263 rtexture_t *r_texture_grey128;
264 rtexture_t *r_texture_black;
265 rtexture_t *r_texture_notexture;
266 rtexture_t *r_texture_whitecube;
267 rtexture_t *r_texture_normalizationcube;
268 rtexture_t *r_texture_fogattenuation;
269 rtexture_t *r_texture_fogheighttexture;
270 rtexture_t *r_texture_gammaramps;
271 unsigned int r_texture_gammaramps_serial;
272 //rtexture_t *r_texture_fogintensity;
273 rtexture_t *r_texture_reflectcube;
274
275 // TODO: hash lookups?
276 typedef struct cubemapinfo_s
277 {
278         char basename[64];
279         rtexture_t *texture;
280 }
281 cubemapinfo_t;
282
283 int r_texture_numcubemaps;
284 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
285
286 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
287 unsigned int r_numqueries;
288 unsigned int r_maxqueries;
289
290 typedef struct r_qwskincache_s
291 {
292         char name[MAX_QPATH];
293         skinframe_t *skinframe;
294 }
295 r_qwskincache_t;
296
297 static r_qwskincache_t *r_qwskincache;
298 static int r_qwskincache_size;
299
300 /// vertex coordinates for a quad that covers the screen exactly
301 extern const float r_screenvertex3f[12];
302 extern const float r_d3dscreenvertex3f[12];
303 const float r_screenvertex3f[12] =
304 {
305         0, 0, 0,
306         1, 0, 0,
307         1, 1, 0,
308         0, 1, 0
309 };
310 const float r_d3dscreenvertex3f[12] =
311 {
312         0, 1, 0,
313         1, 1, 0,
314         1, 0, 0,
315         0, 0, 0
316 };
317
318 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
319 {
320         int i;
321         for (i = 0;i < verts;i++)
322         {
323                 out[0] = in[0] * r;
324                 out[1] = in[1] * g;
325                 out[2] = in[2] * b;
326                 out[3] = in[3];
327                 in += 4;
328                 out += 4;
329         }
330 }
331
332 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
333 {
334         int i;
335         for (i = 0;i < verts;i++)
336         {
337                 out[0] = r;
338                 out[1] = g;
339                 out[2] = b;
340                 out[3] = a;
341                 out += 4;
342         }
343 }
344
345 // FIXME: move this to client?
346 void FOG_clear(void)
347 {
348         if (gamemode == GAME_NEHAHRA)
349         {
350                 Cvar_Set("gl_fogenable", "0");
351                 Cvar_Set("gl_fogdensity", "0.2");
352                 Cvar_Set("gl_fogred", "0.3");
353                 Cvar_Set("gl_foggreen", "0.3");
354                 Cvar_Set("gl_fogblue", "0.3");
355         }
356         r_refdef.fog_density = 0;
357         r_refdef.fog_red = 0;
358         r_refdef.fog_green = 0;
359         r_refdef.fog_blue = 0;
360         r_refdef.fog_alpha = 1;
361         r_refdef.fog_start = 0;
362         r_refdef.fog_end = 16384;
363         r_refdef.fog_height = 1<<30;
364         r_refdef.fog_fadedepth = 128;
365         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
366 }
367
368 static void R_BuildBlankTextures(void)
369 {
370         unsigned char data[4];
371         data[2] = 128; // normal X
372         data[1] = 128; // normal Y
373         data[0] = 255; // normal Z
374         data[3] = 255; // height
375         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
376         data[0] = 255;
377         data[1] = 255;
378         data[2] = 255;
379         data[3] = 255;
380         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
381         data[0] = 128;
382         data[1] = 128;
383         data[2] = 128;
384         data[3] = 255;
385         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
386         data[0] = 0;
387         data[1] = 0;
388         data[2] = 0;
389         data[3] = 255;
390         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
391 }
392
393 static void R_BuildNoTexture(void)
394 {
395         int x, y;
396         unsigned char pix[16][16][4];
397         // this makes a light grey/dark grey checkerboard texture
398         for (y = 0;y < 16;y++)
399         {
400                 for (x = 0;x < 16;x++)
401                 {
402                         if ((y < 8) ^ (x < 8))
403                         {
404                                 pix[y][x][0] = 128;
405                                 pix[y][x][1] = 128;
406                                 pix[y][x][2] = 128;
407                                 pix[y][x][3] = 255;
408                         }
409                         else
410                         {
411                                 pix[y][x][0] = 64;
412                                 pix[y][x][1] = 64;
413                                 pix[y][x][2] = 64;
414                                 pix[y][x][3] = 255;
415                         }
416                 }
417         }
418         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
419 }
420
421 static void R_BuildWhiteCube(void)
422 {
423         unsigned char data[6*1*1*4];
424         memset(data, 255, sizeof(data));
425         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
426 }
427
428 static void R_BuildNormalizationCube(void)
429 {
430         int x, y, side;
431         vec3_t v;
432         vec_t s, t, intensity;
433 #define NORMSIZE 64
434         unsigned char *data;
435         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
436         for (side = 0;side < 6;side++)
437         {
438                 for (y = 0;y < NORMSIZE;y++)
439                 {
440                         for (x = 0;x < NORMSIZE;x++)
441                         {
442                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
443                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
444                                 switch(side)
445                                 {
446                                 default:
447                                 case 0:
448                                         v[0] = 1;
449                                         v[1] = -t;
450                                         v[2] = -s;
451                                         break;
452                                 case 1:
453                                         v[0] = -1;
454                                         v[1] = -t;
455                                         v[2] = s;
456                                         break;
457                                 case 2:
458                                         v[0] = s;
459                                         v[1] = 1;
460                                         v[2] = t;
461                                         break;
462                                 case 3:
463                                         v[0] = s;
464                                         v[1] = -1;
465                                         v[2] = -t;
466                                         break;
467                                 case 4:
468                                         v[0] = s;
469                                         v[1] = -t;
470                                         v[2] = 1;
471                                         break;
472                                 case 5:
473                                         v[0] = -s;
474                                         v[1] = -t;
475                                         v[2] = -1;
476                                         break;
477                                 }
478                                 intensity = 127.0f / sqrt(DotProduct(v, v));
479                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
480                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
481                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
482                                 data[((side*64+y)*64+x)*4+3] = 255;
483                         }
484                 }
485         }
486         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
487         Mem_Free(data);
488 }
489
490 static void R_BuildFogTexture(void)
491 {
492         int x, b;
493 #define FOGWIDTH 256
494         unsigned char data1[FOGWIDTH][4];
495         //unsigned char data2[FOGWIDTH][4];
496         double d, r, alpha;
497
498         r_refdef.fogmasktable_start = r_refdef.fog_start;
499         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
500         r_refdef.fogmasktable_range = r_refdef.fogrange;
501         r_refdef.fogmasktable_density = r_refdef.fog_density;
502
503         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
504         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
505         {
506                 d = (x * r - r_refdef.fogmasktable_start);
507                 if(developer_extra.integer)
508                         Con_DPrintf("%f ", d);
509                 d = max(0, d);
510                 if (r_fog_exp2.integer)
511                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
512                 else
513                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
514                 if(developer_extra.integer)
515                         Con_DPrintf(" : %f ", alpha);
516                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
517                 if(developer_extra.integer)
518                         Con_DPrintf(" = %f\n", alpha);
519                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
520         }
521
522         for (x = 0;x < FOGWIDTH;x++)
523         {
524                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
525                 data1[x][0] = b;
526                 data1[x][1] = b;
527                 data1[x][2] = b;
528                 data1[x][3] = 255;
529                 //data2[x][0] = 255 - b;
530                 //data2[x][1] = 255 - b;
531                 //data2[x][2] = 255 - b;
532                 //data2[x][3] = 255;
533         }
534         if (r_texture_fogattenuation)
535         {
536                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
537                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
538         }
539         else
540         {
541                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
542                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
543         }
544 }
545
546 static void R_BuildFogHeightTexture(void)
547 {
548         unsigned char *inpixels;
549         int size;
550         int x;
551         int y;
552         int j;
553         float c[4];
554         float f;
555         inpixels = NULL;
556         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
557         if (r_refdef.fogheighttexturename[0])
558                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
559         if (!inpixels)
560         {
561                 r_refdef.fog_height_tablesize = 0;
562                 if (r_texture_fogheighttexture)
563                         R_FreeTexture(r_texture_fogheighttexture);
564                 r_texture_fogheighttexture = NULL;
565                 if (r_refdef.fog_height_table2d)
566                         Mem_Free(r_refdef.fog_height_table2d);
567                 r_refdef.fog_height_table2d = NULL;
568                 if (r_refdef.fog_height_table1d)
569                         Mem_Free(r_refdef.fog_height_table1d);
570                 r_refdef.fog_height_table1d = NULL;
571                 return;
572         }
573         size = image_width;
574         r_refdef.fog_height_tablesize = size;
575         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
576         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
577         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
578         Mem_Free(inpixels);
579         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
580         // average fog color table accounting for every fog layer between a point
581         // and the camera.  (Note: attenuation is handled separately!)
582         for (y = 0;y < size;y++)
583         {
584                 for (x = 0;x < size;x++)
585                 {
586                         Vector4Clear(c);
587                         f = 0;
588                         if (x < y)
589                         {
590                                 for (j = x;j <= y;j++)
591                                 {
592                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
593                                         f++;
594                                 }
595                         }
596                         else
597                         {
598                                 for (j = x;j >= y;j--)
599                                 {
600                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
601                                         f++;
602                                 }
603                         }
604                         f = 1.0f / f;
605                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
606                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
607                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
608                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
609                 }
610         }
611         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
612 }
613
614 //=======================================================================================================================================================
615
616 static const char *builtinshaderstrings[] =
617 {
618 #include "shader_glsl.h"
619 0
620 };
621
622 const char *builtinhlslshaderstrings[] =
623 {
624 #include "shader_hlsl.h"
625 0
626 };
627
628 char *glslshaderstring = NULL;
629 char *hlslshaderstring = NULL;
630
631 //=======================================================================================================================================================
632
633 typedef struct shaderpermutationinfo_s
634 {
635         const char *pretext;
636         const char *name;
637 }
638 shaderpermutationinfo_t;
639
640 typedef struct shadermodeinfo_s
641 {
642         const char *filename;
643         const char *pretext;
644         const char *name;
645 }
646 shadermodeinfo_t;
647
648 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
649 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
650 {
651         {"#define USEDIFFUSE\n", " diffuse"},
652         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
653         {"#define USEVIEWTINT\n", " viewtint"},
654         {"#define USECOLORMAPPING\n", " colormapping"},
655         {"#define USESATURATION\n", " saturation"},
656         {"#define USEFOGINSIDE\n", " foginside"},
657         {"#define USEFOGOUTSIDE\n", " fogoutside"},
658         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
659         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
660         {"#define USEGAMMARAMPS\n", " gammaramps"},
661         {"#define USECUBEFILTER\n", " cubefilter"},
662         {"#define USEGLOW\n", " glow"},
663         {"#define USEBLOOM\n", " bloom"},
664         {"#define USESPECULAR\n", " specular"},
665         {"#define USEPOSTPROCESSING\n", " postprocessing"},
666         {"#define USEREFLECTION\n", " reflection"},
667         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
668         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
669         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
670         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
671         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
672         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
673         {"#define USEALPHAKILL\n", " alphakill"},
674         {"#define USEREFLECTCUBE\n", " reflectcube"},
675         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
676         {"#define USEBOUNCEGRID\n", " bouncegrid"},
677         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
678         {"#define USETRIPPY\n", " trippy"},
679         {"#define USEDEPTHRGB\n", " depthrgb"},
680         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
681         {"#define USESKELETAL\n", " skeletal"},
682         {"#define USEOCCLUDE\n", " occlude"}
683 };
684
685 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
686 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
687 {
688         {"glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
689         {"glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
690         {"glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
691         {"glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
692         {"glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
693         {"glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
694         {"glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
695         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
696         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
697         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
698         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
699         {"glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
700         {"glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
701         {"glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
702         {"glsl/default.glsl", "#define MODE_WATER\n", " water"},
703         {"glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
704         {"glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
705 };
706
707 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
708 {
709         {"hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
710         {"hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
711         {"hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
712         {"hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
713         {"hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
714         {"hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
715         {"hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
716         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
717         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
718         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
719         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
720         {"hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
721         {"hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
722         {"hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
723         {"hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
724         {"hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
725         {"hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
726 };
727
728 struct r_glsl_permutation_s;
729 typedef struct r_glsl_permutation_s
730 {
731         /// hash lookup data
732         struct r_glsl_permutation_s *hashnext;
733         unsigned int mode;
734         unsigned int permutation;
735
736         /// indicates if we have tried compiling this permutation already
737         qboolean compiled;
738         /// 0 if compilation failed
739         int program;
740         // texture units assigned to each detected uniform
741         int tex_Texture_First;
742         int tex_Texture_Second;
743         int tex_Texture_GammaRamps;
744         int tex_Texture_Normal;
745         int tex_Texture_Color;
746         int tex_Texture_Gloss;
747         int tex_Texture_Glow;
748         int tex_Texture_SecondaryNormal;
749         int tex_Texture_SecondaryColor;
750         int tex_Texture_SecondaryGloss;
751         int tex_Texture_SecondaryGlow;
752         int tex_Texture_Pants;
753         int tex_Texture_Shirt;
754         int tex_Texture_FogHeightTexture;
755         int tex_Texture_FogMask;
756         int tex_Texture_Lightmap;
757         int tex_Texture_Deluxemap;
758         int tex_Texture_Attenuation;
759         int tex_Texture_Cube;
760         int tex_Texture_Refraction;
761         int tex_Texture_Reflection;
762         int tex_Texture_ShadowMap2D;
763         int tex_Texture_CubeProjection;
764         int tex_Texture_ScreenNormalMap;
765         int tex_Texture_ScreenDiffuse;
766         int tex_Texture_ScreenSpecular;
767         int tex_Texture_ReflectMask;
768         int tex_Texture_ReflectCube;
769         int tex_Texture_BounceGrid;
770         /// locations of detected uniforms in program object, or -1 if not found
771         int loc_Texture_First;
772         int loc_Texture_Second;
773         int loc_Texture_GammaRamps;
774         int loc_Texture_Normal;
775         int loc_Texture_Color;
776         int loc_Texture_Gloss;
777         int loc_Texture_Glow;
778         int loc_Texture_SecondaryNormal;
779         int loc_Texture_SecondaryColor;
780         int loc_Texture_SecondaryGloss;
781         int loc_Texture_SecondaryGlow;
782         int loc_Texture_Pants;
783         int loc_Texture_Shirt;
784         int loc_Texture_FogHeightTexture;
785         int loc_Texture_FogMask;
786         int loc_Texture_Lightmap;
787         int loc_Texture_Deluxemap;
788         int loc_Texture_Attenuation;
789         int loc_Texture_Cube;
790         int loc_Texture_Refraction;
791         int loc_Texture_Reflection;
792         int loc_Texture_ShadowMap2D;
793         int loc_Texture_CubeProjection;
794         int loc_Texture_ScreenNormalMap;
795         int loc_Texture_ScreenDiffuse;
796         int loc_Texture_ScreenSpecular;
797         int loc_Texture_ReflectMask;
798         int loc_Texture_ReflectCube;
799         int loc_Texture_BounceGrid;
800         int loc_Alpha;
801         int loc_BloomBlur_Parameters;
802         int loc_ClientTime;
803         int loc_Color_Ambient;
804         int loc_Color_Diffuse;
805         int loc_Color_Specular;
806         int loc_Color_Glow;
807         int loc_Color_Pants;
808         int loc_Color_Shirt;
809         int loc_DeferredColor_Ambient;
810         int loc_DeferredColor_Diffuse;
811         int loc_DeferredColor_Specular;
812         int loc_DeferredMod_Diffuse;
813         int loc_DeferredMod_Specular;
814         int loc_DistortScaleRefractReflect;
815         int loc_EyePosition;
816         int loc_FogColor;
817         int loc_FogHeightFade;
818         int loc_FogPlane;
819         int loc_FogPlaneViewDist;
820         int loc_FogRangeRecip;
821         int loc_LightColor;
822         int loc_LightDir;
823         int loc_LightPosition;
824         int loc_OffsetMapping_ScaleSteps;
825         int loc_OffsetMapping_LodDistance;
826         int loc_OffsetMapping_Bias;
827         int loc_PixelSize;
828         int loc_ReflectColor;
829         int loc_ReflectFactor;
830         int loc_ReflectOffset;
831         int loc_RefractColor;
832         int loc_Saturation;
833         int loc_ScreenCenterRefractReflect;
834         int loc_ScreenScaleRefractReflect;
835         int loc_ScreenToDepth;
836         int loc_ShadowMap_Parameters;
837         int loc_ShadowMap_TextureScale;
838         int loc_SpecularPower;
839         int loc_Skeletal_Transform12;
840         int loc_UserVec1;
841         int loc_UserVec2;
842         int loc_UserVec3;
843         int loc_UserVec4;
844         int loc_ViewTintColor;
845         int loc_ViewToLight;
846         int loc_ModelToLight;
847         int loc_TexMatrix;
848         int loc_BackgroundTexMatrix;
849         int loc_ModelViewProjectionMatrix;
850         int loc_ModelViewMatrix;
851         int loc_PixelToScreenTexCoord;
852         int loc_ModelToReflectCube;
853         int loc_ShadowMapMatrix;
854         int loc_BloomColorSubtract;
855         int loc_NormalmapScrollBlend;
856         int loc_BounceGridMatrix;
857         int loc_BounceGridIntensity;
858         /// uniform block bindings
859         int ubibind_Skeletal_Transform12_UniformBlock;
860         /// uniform block indices
861         int ubiloc_Skeletal_Transform12_UniformBlock;
862 }
863 r_glsl_permutation_t;
864
865 #define SHADERPERMUTATION_HASHSIZE 256
866
867
868 // non-degradable "lightweight" shader parameters to keep the permutations simpler
869 // these can NOT degrade! only use for simple stuff
870 enum
871 {
872         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
873         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
874         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
875         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
876         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
877         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
878         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
879         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
880         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
881         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
882         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
883         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
884         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
885         SHADERSTATICPARM_FXAA = 13 ///< fast approximate anti aliasing
886 };
887 #define SHADERSTATICPARMS_COUNT 14
888
889 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
890 static int shaderstaticparms_count = 0;
891
892 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
893 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
894
895 extern qboolean r_shadow_shadowmapsampler;
896 extern int r_shadow_shadowmappcf;
897 qboolean R_CompileShader_CheckStaticParms(void)
898 {
899         static int r_compileshader_staticparms_save[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5];
900         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
901         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
902
903         // detect all
904         if (r_glsl_saturation_redcompensate.integer)
905                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
906         if (r_glsl_vertextextureblend_usebothalphas.integer)
907                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
908         if (r_shadow_glossexact.integer)
909                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
910         if (r_glsl_postprocess.integer)
911         {
912                 if (r_glsl_postprocess_uservec1_enable.integer)
913                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
914                 if (r_glsl_postprocess_uservec2_enable.integer)
915                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
916                 if (r_glsl_postprocess_uservec3_enable.integer)
917                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
918                 if (r_glsl_postprocess_uservec4_enable.integer)
919                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
920         }
921         if (r_fxaa.integer)
922                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_FXAA);
923         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
924                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
925
926         if (r_shadow_shadowmapsampler)
927                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
928         if (r_shadow_shadowmappcf > 1)
929                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
930         else if (r_shadow_shadowmappcf)
931                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
932         if (r_celshading.integer)
933                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
934         if (r_celoutlines.integer)
935                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
936
937         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
938 }
939
940 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
941         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
942                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
943         else \
944                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
945 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
946 {
947         shaderstaticparms_count = 0;
948
949         // emit all
950         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
951         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
952         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
953         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
954         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
955         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
956         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
957         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
958         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
959         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
960         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
961         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
962         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
963         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_FXAA, "USEFXAA");
964 }
965
966 /// information about each possible shader permutation
967 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
968 /// currently selected permutation
969 r_glsl_permutation_t *r_glsl_permutation;
970 /// storage for permutations linked in the hash table
971 memexpandablearray_t r_glsl_permutationarray;
972
973 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
974 {
975         //unsigned int hashdepth = 0;
976         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
977         r_glsl_permutation_t *p;
978         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
979         {
980                 if (p->mode == mode && p->permutation == permutation)
981                 {
982                         //if (hashdepth > 10)
983                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
984                         return p;
985                 }
986                 //hashdepth++;
987         }
988         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
989         p->mode = mode;
990         p->permutation = permutation;
991         p->hashnext = r_glsl_permutationhash[mode][hashindex];
992         r_glsl_permutationhash[mode][hashindex] = p;
993         //if (hashdepth > 10)
994         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
995         return p;
996 }
997
998 static char *R_ShaderStrCat(const char **strings)
999 {
1000         char *string, *s;
1001         const char **p = strings;
1002         const char *t;
1003         size_t len = 0;
1004         for (p = strings;(t = *p);p++)
1005                 len += strlen(t);
1006         len++;
1007         s = string = (char *)Mem_Alloc(r_main_mempool, len);
1008         len = 0;
1009         for (p = strings;(t = *p);p++)
1010         {
1011                 len = strlen(t);
1012                 memcpy(s, t, len);
1013                 s += len;
1014         }
1015         *s = 0;
1016         return string;
1017 }
1018
1019 static char *R_GetShaderText(const char *filename, qboolean printfromdisknotice, qboolean builtinonly)
1020 {
1021         char *shaderstring;
1022         if (!filename || !filename[0])
1023                 return NULL;
1024         // LordHavoc: note that FS_LoadFile appends a 0 byte to make it a valid string, so does R_ShaderStrCat
1025         if (!strcmp(filename, "glsl/default.glsl"))
1026         {
1027                 if (builtinonly)
1028                         return R_ShaderStrCat(builtinshaderstrings);
1029                 if (!glslshaderstring)
1030                 {
1031                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1032                         if (glslshaderstring)
1033                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1034                         else
1035                                 glslshaderstring = R_ShaderStrCat(builtinshaderstrings);
1036                 }
1037                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
1038                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
1039                 return shaderstring;
1040         }
1041         if (!strcmp(filename, "hlsl/default.hlsl"))
1042         {
1043                 if (builtinonly)
1044                         return R_ShaderStrCat(builtinhlslshaderstrings);
1045                 if (!hlslshaderstring)
1046                 {
1047                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1048                         if (hlslshaderstring)
1049                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1050                         else
1051                                 hlslshaderstring = R_ShaderStrCat(builtinhlslshaderstrings);
1052                 }
1053                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1054                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1055                 return shaderstring;
1056         }
1057         // we don't have builtin strings for any other files
1058         if (builtinonly)
1059                 return NULL;
1060         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1061         if (shaderstring)
1062         {
1063                 if (printfromdisknotice)
1064                         Con_DPrintf("from disk %s... ", filename);
1065                 return shaderstring;
1066         }
1067         return shaderstring;
1068 }
1069
1070 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1071 {
1072         int i;
1073         int ubibind;
1074         int sampler;
1075         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1076         char *sourcestring;
1077         char permutationname[256];
1078         int vertstrings_count = 0;
1079         int geomstrings_count = 0;
1080         int fragstrings_count = 0;
1081         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1082         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1083         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1084
1085         if (p->compiled)
1086                 return;
1087         p->compiled = true;
1088         p->program = 0;
1089
1090         permutationname[0] = 0;
1091         sourcestring  = R_GetShaderText(modeinfo->filename, true, false);
1092
1093         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1094
1095         // we need 140 for r_glsl_skeletal (GL_ARB_uniform_buffer_object)
1096         if(vid.support.glshaderversion >= 140)
1097         {
1098                 vertstrings_list[vertstrings_count++] = "#version 140\n";
1099                 geomstrings_list[geomstrings_count++] = "#version 140\n";
1100                 fragstrings_list[fragstrings_count++] = "#version 140\n";
1101                 vertstrings_list[vertstrings_count++] = "#define GLSL140\n";
1102                 geomstrings_list[geomstrings_count++] = "#define GLSL140\n";
1103                 fragstrings_list[fragstrings_count++] = "#define GLSL140\n";
1104         }
1105         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1106         else if(vid.support.glshaderversion >= 130)
1107         {
1108                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1109                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1110                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1111                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1112                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1113                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1114         }
1115
1116         // the first pretext is which type of shader to compile as
1117         // (later these will all be bound together as a program object)
1118         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1119         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1120         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1121
1122         // the second pretext is the mode (for example a light source)
1123         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1124         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1125         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1126         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1127
1128         // now add all the permutation pretexts
1129         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1130         {
1131                 if (permutation & (1<<i))
1132                 {
1133                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1134                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1135                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1136                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1137                 }
1138                 else
1139                 {
1140                         // keep line numbers correct
1141                         vertstrings_list[vertstrings_count++] = "\n";
1142                         geomstrings_list[geomstrings_count++] = "\n";
1143                         fragstrings_list[fragstrings_count++] = "\n";
1144                 }
1145         }
1146
1147         // add static parms
1148         R_CompileShader_AddStaticParms(mode, permutation);
1149         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1150         vertstrings_count += shaderstaticparms_count;
1151         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1152         geomstrings_count += shaderstaticparms_count;
1153         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1154         fragstrings_count += shaderstaticparms_count;
1155
1156         // now append the shader text itself
1157         vertstrings_list[vertstrings_count++] = sourcestring;
1158         geomstrings_list[geomstrings_count++] = sourcestring;
1159         fragstrings_list[fragstrings_count++] = sourcestring;
1160
1161         // compile the shader program
1162         if (vertstrings_count + geomstrings_count + fragstrings_count)
1163                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1164         if (p->program)
1165         {
1166                 CHECKGLERROR
1167                 qglUseProgram(p->program);CHECKGLERROR
1168                 // look up all the uniform variable names we care about, so we don't
1169                 // have to look them up every time we set them
1170
1171 #if 0
1172                 // debugging aid
1173                 {
1174                         GLint activeuniformindex = 0;
1175                         GLint numactiveuniforms = 0;
1176                         char uniformname[128];
1177                         GLsizei uniformnamelength = 0;
1178                         GLint uniformsize = 0;
1179                         GLenum uniformtype = 0;
1180                         memset(uniformname, 0, sizeof(uniformname));
1181                         qglGetProgramiv(p->program, GL_ACTIVE_UNIFORMS, &numactiveuniforms);
1182                         Con_Printf("Shader has %i uniforms\n", numactiveuniforms);
1183                         for (activeuniformindex = 0;activeuniformindex < numactiveuniforms;activeuniformindex++)
1184                         {
1185                                 qglGetActiveUniform(p->program, activeuniformindex, sizeof(uniformname) - 1, &uniformnamelength, &uniformsize, &uniformtype, uniformname);
1186                                 Con_Printf("Uniform %i name \"%s\" size %i type %i\n", (int)activeuniformindex, uniformname, (int)uniformsize, (int)uniformtype);
1187                         }
1188                 }
1189 #endif
1190
1191                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1192                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1193                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1194                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1195                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1196                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1197                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1198                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1199                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1200                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1201                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1202                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1203                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1204                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1205                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1206                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1207                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1208                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1209                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1210                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1211                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1212                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1213                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1214                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1215                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1216                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1217                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1218                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1219                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1220                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1221                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1222                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1223                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1224                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1225                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1226                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1227                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1228                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1229                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1230                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1231                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1232                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1233                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1234                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1235                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1236                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1237                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1238                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1239                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1240                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1241                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1242                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1243                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1244                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1245                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1246                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1247                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1248                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1249                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1250                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1251                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1252                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1253                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1254                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1255                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1256                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1257                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1258                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1259                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1260                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1261                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1262                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1263                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1264                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1265                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1266                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1267                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1268                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1269                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1270                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1271                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1272                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1273                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1274                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1275                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1276                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1277                 // initialize the samplers to refer to the texture units we use
1278                 p->tex_Texture_First = -1;
1279                 p->tex_Texture_Second = -1;
1280                 p->tex_Texture_GammaRamps = -1;
1281                 p->tex_Texture_Normal = -1;
1282                 p->tex_Texture_Color = -1;
1283                 p->tex_Texture_Gloss = -1;
1284                 p->tex_Texture_Glow = -1;
1285                 p->tex_Texture_SecondaryNormal = -1;
1286                 p->tex_Texture_SecondaryColor = -1;
1287                 p->tex_Texture_SecondaryGloss = -1;
1288                 p->tex_Texture_SecondaryGlow = -1;
1289                 p->tex_Texture_Pants = -1;
1290                 p->tex_Texture_Shirt = -1;
1291                 p->tex_Texture_FogHeightTexture = -1;
1292                 p->tex_Texture_FogMask = -1;
1293                 p->tex_Texture_Lightmap = -1;
1294                 p->tex_Texture_Deluxemap = -1;
1295                 p->tex_Texture_Attenuation = -1;
1296                 p->tex_Texture_Cube = -1;
1297                 p->tex_Texture_Refraction = -1;
1298                 p->tex_Texture_Reflection = -1;
1299                 p->tex_Texture_ShadowMap2D = -1;
1300                 p->tex_Texture_CubeProjection = -1;
1301                 p->tex_Texture_ScreenNormalMap = -1;
1302                 p->tex_Texture_ScreenDiffuse = -1;
1303                 p->tex_Texture_ScreenSpecular = -1;
1304                 p->tex_Texture_ReflectMask = -1;
1305                 p->tex_Texture_ReflectCube = -1;
1306                 p->tex_Texture_BounceGrid = -1;
1307                 // bind the texture samplers in use
1308                 sampler = 0;
1309                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1310                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1311                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1312                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1313                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1314                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1315                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1316                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1317                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1318                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1319                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1320                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1321                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1322                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1323                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1324                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1325                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1326                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1327                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1328                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1329                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1330                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1331                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1332                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1333                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1334                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1335                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1336                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1337                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1338                 // get the uniform block indices so we can bind them
1339 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1340                 if (vid.support.arb_uniform_buffer_object)
1341                         p->ubiloc_Skeletal_Transform12_UniformBlock = qglGetUniformBlockIndex(p->program, "Skeletal_Transform12_UniformBlock");
1342                 else
1343 #endif
1344                         p->ubiloc_Skeletal_Transform12_UniformBlock = -1;
1345                 // clear the uniform block bindings
1346                 p->ubibind_Skeletal_Transform12_UniformBlock = -1;
1347                 // bind the uniform blocks in use
1348                 ubibind = 0;
1349 #ifndef USE_GLES2 /* FIXME: GLES3 only */
1350                 if (p->ubiloc_Skeletal_Transform12_UniformBlock >= 0) {p->ubibind_Skeletal_Transform12_UniformBlock = ubibind;qglUniformBlockBinding(p->program, p->ubiloc_Skeletal_Transform12_UniformBlock, ubibind);ubibind++;}
1351 #endif
1352                 // we're done compiling and setting up the shader, at least until it is used
1353                 CHECKGLERROR
1354                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1355         }
1356         else
1357                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1358
1359         // free the strings
1360         if (sourcestring)
1361                 Mem_Free(sourcestring);
1362 }
1363
1364 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1365 {
1366         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1367         if (r_glsl_permutation != perm)
1368         {
1369                 r_glsl_permutation = perm;
1370                 if (!r_glsl_permutation->program)
1371                 {
1372                         if (!r_glsl_permutation->compiled)
1373                         {
1374                                 Con_DPrintf("Compiling shader mode %u permutation %u\n", mode, permutation);
1375                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1376                         }
1377                         if (!r_glsl_permutation->program)
1378                         {
1379                                 // remove features until we find a valid permutation
1380                                 int i;
1381                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1382                                 {
1383                                         // reduce i more quickly whenever it would not remove any bits
1384                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1385                                         if (!(permutation & j))
1386                                                 continue;
1387                                         permutation -= j;
1388                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1389                                         if (!r_glsl_permutation->compiled)
1390                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1391                                         if (r_glsl_permutation->program)
1392                                                 break;
1393                                 }
1394                                 if (i >= SHADERPERMUTATION_COUNT)
1395                                 {
1396                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1397                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1398                                         qglUseProgram(0);CHECKGLERROR
1399                                         return; // no bit left to clear, entire mode is broken
1400                                 }
1401                         }
1402                 }
1403                 CHECKGLERROR
1404                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1405         }
1406         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1407         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1408         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1409         CHECKGLERROR
1410 }
1411
1412 #ifdef SUPPORTD3D
1413
1414 #ifdef SUPPORTD3D
1415 #include <d3d9.h>
1416 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1417 extern D3DCAPS9 vid_d3d9caps;
1418 #endif
1419
1420 struct r_hlsl_permutation_s;
1421 typedef struct r_hlsl_permutation_s
1422 {
1423         /// hash lookup data
1424         struct r_hlsl_permutation_s *hashnext;
1425         unsigned int mode;
1426         unsigned int permutation;
1427
1428         /// indicates if we have tried compiling this permutation already
1429         qboolean compiled;
1430         /// NULL if compilation failed
1431         IDirect3DVertexShader9 *vertexshader;
1432         IDirect3DPixelShader9 *pixelshader;
1433 }
1434 r_hlsl_permutation_t;
1435
1436 typedef enum D3DVSREGISTER_e
1437 {
1438         D3DVSREGISTER_TexMatrix = 0, // float4x4
1439         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1440         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1441         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1442         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1443         D3DVSREGISTER_ModelToLight = 20, // float4x4
1444         D3DVSREGISTER_EyePosition = 24,
1445         D3DVSREGISTER_FogPlane = 25,
1446         D3DVSREGISTER_LightDir = 26,
1447         D3DVSREGISTER_LightPosition = 27,
1448 }
1449 D3DVSREGISTER_t;
1450
1451 typedef enum D3DPSREGISTER_e
1452 {
1453         D3DPSREGISTER_Alpha = 0,
1454         D3DPSREGISTER_BloomBlur_Parameters = 1,
1455         D3DPSREGISTER_ClientTime = 2,
1456         D3DPSREGISTER_Color_Ambient = 3,
1457         D3DPSREGISTER_Color_Diffuse = 4,
1458         D3DPSREGISTER_Color_Specular = 5,
1459         D3DPSREGISTER_Color_Glow = 6,
1460         D3DPSREGISTER_Color_Pants = 7,
1461         D3DPSREGISTER_Color_Shirt = 8,
1462         D3DPSREGISTER_DeferredColor_Ambient = 9,
1463         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1464         D3DPSREGISTER_DeferredColor_Specular = 11,
1465         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1466         D3DPSREGISTER_DeferredMod_Specular = 13,
1467         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1468         D3DPSREGISTER_EyePosition = 15, // unused
1469         D3DPSREGISTER_FogColor = 16,
1470         D3DPSREGISTER_FogHeightFade = 17,
1471         D3DPSREGISTER_FogPlane = 18,
1472         D3DPSREGISTER_FogPlaneViewDist = 19,
1473         D3DPSREGISTER_FogRangeRecip = 20,
1474         D3DPSREGISTER_LightColor = 21,
1475         D3DPSREGISTER_LightDir = 22, // unused
1476         D3DPSREGISTER_LightPosition = 23,
1477         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1478         D3DPSREGISTER_PixelSize = 25,
1479         D3DPSREGISTER_ReflectColor = 26,
1480         D3DPSREGISTER_ReflectFactor = 27,
1481         D3DPSREGISTER_ReflectOffset = 28,
1482         D3DPSREGISTER_RefractColor = 29,
1483         D3DPSREGISTER_Saturation = 30,
1484         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1485         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1486         D3DPSREGISTER_ScreenToDepth = 33,
1487         D3DPSREGISTER_ShadowMap_Parameters = 34,
1488         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1489         D3DPSREGISTER_SpecularPower = 36,
1490         D3DPSREGISTER_UserVec1 = 37,
1491         D3DPSREGISTER_UserVec2 = 38,
1492         D3DPSREGISTER_UserVec3 = 39,
1493         D3DPSREGISTER_UserVec4 = 40,
1494         D3DPSREGISTER_ViewTintColor = 41,
1495         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1496         D3DPSREGISTER_BloomColorSubtract = 43,
1497         D3DPSREGISTER_ViewToLight = 44, // float4x4
1498         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1499         D3DPSREGISTER_NormalmapScrollBlend = 52,
1500         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1501         D3DPSREGISTER_OffsetMapping_Bias = 54,
1502         // next at 54
1503 }
1504 D3DPSREGISTER_t;
1505
1506 /// information about each possible shader permutation
1507 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1508 /// currently selected permutation
1509 r_hlsl_permutation_t *r_hlsl_permutation;
1510 /// storage for permutations linked in the hash table
1511 memexpandablearray_t r_hlsl_permutationarray;
1512
1513 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1514 {
1515         //unsigned int hashdepth = 0;
1516         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1517         r_hlsl_permutation_t *p;
1518         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1519         {
1520                 if (p->mode == mode && p->permutation == permutation)
1521                 {
1522                         //if (hashdepth > 10)
1523                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1524                         return p;
1525                 }
1526                 //hashdepth++;
1527         }
1528         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1529         p->mode = mode;
1530         p->permutation = permutation;
1531         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1532         r_hlsl_permutationhash[mode][hashindex] = p;
1533         //if (hashdepth > 10)
1534         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1535         return p;
1536 }
1537
1538 #include <d3dx9.h>
1539 //#include <d3dx9shader.h>
1540 //#include <d3dx9mesh.h>
1541
1542 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1543 {
1544         DWORD *vsbin = NULL;
1545         DWORD *psbin = NULL;
1546         fs_offset_t vsbinsize;
1547         fs_offset_t psbinsize;
1548 //      IDirect3DVertexShader9 *vs = NULL;
1549 //      IDirect3DPixelShader9 *ps = NULL;
1550         ID3DXBuffer *vslog = NULL;
1551         ID3DXBuffer *vsbuffer = NULL;
1552         ID3DXConstantTable *vsconstanttable = NULL;
1553         ID3DXBuffer *pslog = NULL;
1554         ID3DXBuffer *psbuffer = NULL;
1555         ID3DXConstantTable *psconstanttable = NULL;
1556         int vsresult = 0;
1557         int psresult = 0;
1558         char temp[MAX_INPUTLINE];
1559         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1560         char vabuf[1024];
1561         qboolean debugshader = gl_paranoid.integer != 0;
1562         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1563         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1564         if (!debugshader)
1565         {
1566                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1567                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1568         }
1569         if ((!vsbin && vertstring) || (!psbin && fragstring))
1570         {
1571                 const char* dllnames_d3dx9 [] =
1572                 {
1573                         "d3dx9_43.dll",
1574                         "d3dx9_42.dll",
1575                         "d3dx9_41.dll",
1576                         "d3dx9_40.dll",
1577                         "d3dx9_39.dll",
1578                         "d3dx9_38.dll",
1579                         "d3dx9_37.dll",
1580                         "d3dx9_36.dll",
1581                         "d3dx9_35.dll",
1582                         "d3dx9_34.dll",
1583                         "d3dx9_33.dll",
1584                         "d3dx9_32.dll",
1585                         "d3dx9_31.dll",
1586                         "d3dx9_30.dll",
1587                         "d3dx9_29.dll",
1588                         "d3dx9_28.dll",
1589                         "d3dx9_27.dll",
1590                         "d3dx9_26.dll",
1591                         "d3dx9_25.dll",
1592                         "d3dx9_24.dll",
1593                         NULL
1594                 };
1595                 dllhandle_t d3dx9_dll = NULL;
1596                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1597                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1598                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1599                 dllfunction_t d3dx9_dllfuncs[] =
1600                 {
1601                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1602                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1603                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1604                         {NULL, NULL}
1605                 };
1606                 // 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...
1607 #ifndef ID3DXBuffer_GetBufferPointer
1608 #if !defined(__cplusplus) || defined(CINTERFACE)
1609 #define ID3DXBuffer_GetBufferPointer(p)   (p)->lpVtbl->GetBufferPointer(p)
1610 #define ID3DXBuffer_GetBufferSize(p)      (p)->lpVtbl->GetBufferSize(p)
1611 #define ID3DXBuffer_Release(p)            (p)->lpVtbl->Release(p)
1612 #else
1613 #define ID3DXBuffer_GetBufferPointer(p)   (p)->GetBufferPointer()
1614 #define ID3DXBuffer_GetBufferSize(p)      (p)->GetBufferSize()
1615 #define ID3DXBuffer_Release(p)            (p)->Release()
1616 #endif
1617 #endif
1618                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1619                 {
1620                         DWORD shaderflags = 0;
1621                         if (debugshader)
1622                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1623                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1624                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1625                         if (vertstring && vertstring[0])
1626                         {
1627                                 if (debugshader)
1628                                 {
1629                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1630                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1631                                 }
1632                                 else
1633                                         vsresult = qD3DXCompileShader(vertstring, (unsigned int)strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1634                                 if (vsbuffer)
1635                                 {
1636                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1637                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1638                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1639                                         ID3DXBuffer_Release(vsbuffer);
1640                                 }
1641                                 if (vslog)
1642                                 {
1643                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1644                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1645                                         ID3DXBuffer_Release(vslog);
1646                                 }
1647                         }
1648                         if (fragstring && fragstring[0])
1649                         {
1650                                 if (debugshader)
1651                                 {
1652                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1653                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1654                                 }
1655                                 else
1656                                         psresult = qD3DXCompileShader(fragstring, (unsigned int)strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1657                                 if (psbuffer)
1658                                 {
1659                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1660                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1661                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1662                                         ID3DXBuffer_Release(psbuffer);
1663                                 }
1664                                 if (pslog)
1665                                 {
1666                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1667                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1668                                         ID3DXBuffer_Release(pslog);
1669                                 }
1670                         }
1671                         Sys_UnloadLibrary(&d3dx9_dll);
1672                 }
1673                 else
1674                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1675         }
1676         if (vsbin && psbin)
1677         {
1678                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1679                 if (FAILED(vsresult))
1680                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1681                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1682                 if (FAILED(psresult))
1683                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1684         }
1685         // free the shader data
1686         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1687         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1688 }
1689
1690 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1691 {
1692         int i;
1693         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1694         int vertstring_length = 0;
1695         int geomstring_length = 0;
1696         int fragstring_length = 0;
1697         char *t;
1698         char *sourcestring;
1699         char *vertstring, *geomstring, *fragstring;
1700         char permutationname[256];
1701         char cachename[256];
1702         int vertstrings_count = 0;
1703         int geomstrings_count = 0;
1704         int fragstrings_count = 0;
1705         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1706         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1707         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1708
1709         if (p->compiled)
1710                 return;
1711         p->compiled = true;
1712         p->vertexshader = NULL;
1713         p->pixelshader = NULL;
1714
1715         permutationname[0] = 0;
1716         cachename[0] = 0;
1717         sourcestring = R_GetShaderText(modeinfo->filename, true, false);
1718
1719         strlcat(permutationname, modeinfo->filename, sizeof(permutationname));
1720         strlcat(cachename, "hlsl/", sizeof(cachename));
1721
1722         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1723         vertstrings_count = 0;
1724         geomstrings_count = 0;
1725         fragstrings_count = 0;
1726         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1727         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1728         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1729
1730         // the first pretext is which type of shader to compile as
1731         // (later these will all be bound together as a program object)
1732         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1733         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1734         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1735
1736         // the second pretext is the mode (for example a light source)
1737         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1738         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1739         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1740         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1741         strlcat(cachename, modeinfo->name, sizeof(cachename));
1742
1743         // now add all the permutation pretexts
1744         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1745         {
1746                 if (permutation & (1<<i))
1747                 {
1748                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1749                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1750                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1751                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1752                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1753                 }
1754                 else
1755                 {
1756                         // keep line numbers correct
1757                         vertstrings_list[vertstrings_count++] = "\n";
1758                         geomstrings_list[geomstrings_count++] = "\n";
1759                         fragstrings_list[fragstrings_count++] = "\n";
1760                 }
1761         }
1762
1763         // add static parms
1764         R_CompileShader_AddStaticParms(mode, permutation);
1765         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1766         vertstrings_count += shaderstaticparms_count;
1767         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1768         geomstrings_count += shaderstaticparms_count;
1769         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1770         fragstrings_count += shaderstaticparms_count;
1771
1772         // replace spaces in the cachename with _ characters
1773         for (i = 0;cachename[i];i++)
1774                 if (cachename[i] == ' ')
1775                         cachename[i] = '_';
1776
1777         // now append the shader text itself
1778         vertstrings_list[vertstrings_count++] = sourcestring;
1779         geomstrings_list[geomstrings_count++] = sourcestring;
1780         fragstrings_list[fragstrings_count++] = sourcestring;
1781
1782         vertstring_length = 0;
1783         for (i = 0;i < vertstrings_count;i++)
1784                 vertstring_length += (int)strlen(vertstrings_list[i]);
1785         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1786         for (i = 0;i < vertstrings_count;t += (int)strlen(vertstrings_list[i]), i++)
1787                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1788
1789         geomstring_length = 0;
1790         for (i = 0;i < geomstrings_count;i++)
1791                 geomstring_length += (int)strlen(geomstrings_list[i]);
1792         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1793         for (i = 0;i < geomstrings_count;t += (int)strlen(geomstrings_list[i]), i++)
1794                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1795
1796         fragstring_length = 0;
1797         for (i = 0;i < fragstrings_count;i++)
1798                 fragstring_length += (int)strlen(fragstrings_list[i]);
1799         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1800         for (i = 0;i < fragstrings_count;t += (int)strlen(fragstrings_list[i]), i++)
1801                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1802
1803         // try to load the cached shader, or generate one
1804         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1805
1806         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1807                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1808         else
1809                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1810
1811         // free the strings
1812         if (vertstring)
1813                 Mem_Free(vertstring);
1814         if (geomstring)
1815                 Mem_Free(geomstring);
1816         if (fragstring)
1817                 Mem_Free(fragstring);
1818         if (sourcestring)
1819                 Mem_Free(sourcestring);
1820 }
1821
1822 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1823 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1824 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);}
1825 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);}
1826 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);}
1827 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);}
1828
1829 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1830 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1831 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);}
1832 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);}
1833 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);}
1834 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);}
1835
1836 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1837 {
1838         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1839         if (r_hlsl_permutation != perm)
1840         {
1841                 r_hlsl_permutation = perm;
1842                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1843                 {
1844                         if (!r_hlsl_permutation->compiled)
1845                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1846                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1847                         {
1848                                 // remove features until we find a valid permutation
1849                                 int i;
1850                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1851                                 {
1852                                         // reduce i more quickly whenever it would not remove any bits
1853                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1854                                         if (!(permutation & j))
1855                                                 continue;
1856                                         permutation -= j;
1857                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1858                                         if (!r_hlsl_permutation->compiled)
1859                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1860                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1861                                                 break;
1862                                 }
1863                                 if (i >= SHADERPERMUTATION_COUNT)
1864                                 {
1865                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].filename, shadermodeinfo[mode].pretext);
1866                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1867                                         return; // no bit left to clear, entire mode is broken
1868                                 }
1869                         }
1870                 }
1871                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1872                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1873         }
1874         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1875         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1876         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1877 }
1878 #endif
1879
1880 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1881 {
1882         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1883         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1884         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1885         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1886 }
1887
1888 void R_GLSL_Restart_f(void)
1889 {
1890         unsigned int i, limit;
1891         if (glslshaderstring)
1892                 Mem_Free(glslshaderstring);
1893         glslshaderstring = NULL;
1894         if (hlslshaderstring)
1895                 Mem_Free(hlslshaderstring);
1896         hlslshaderstring = NULL;
1897         switch(vid.renderpath)
1898         {
1899         case RENDERPATH_D3D9:
1900 #ifdef SUPPORTD3D
1901                 {
1902                         r_hlsl_permutation_t *p;
1903                         r_hlsl_permutation = NULL;
1904                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1905                         for (i = 0;i < limit;i++)
1906                         {
1907                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1908                                 {
1909                                         if (p->vertexshader)
1910                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1911                                         if (p->pixelshader)
1912                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1913                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1914                                 }
1915                         }
1916                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1917                 }
1918 #endif
1919                 break;
1920         case RENDERPATH_D3D10:
1921                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1922                 break;
1923         case RENDERPATH_D3D11:
1924                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1925                 break;
1926         case RENDERPATH_GL20:
1927         case RENDERPATH_GLES2:
1928                 {
1929                         r_glsl_permutation_t *p;
1930                         r_glsl_permutation = NULL;
1931                         limit = (unsigned int)Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1932                         for (i = 0;i < limit;i++)
1933                         {
1934                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1935                                 {
1936                                         GL_Backend_FreeProgram(p->program);
1937                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1938                                 }
1939                         }
1940                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1941                 }
1942                 break;
1943         case RENDERPATH_GL11:
1944         case RENDERPATH_GL13:
1945         case RENDERPATH_GLES1:
1946                 break;
1947         case RENDERPATH_SOFT:
1948                 break;
1949         }
1950 }
1951
1952 static void R_GLSL_DumpShader_f(void)
1953 {
1954         int i, language, mode, dupe;
1955         char *text;
1956         shadermodeinfo_t *modeinfo;
1957         qfile_t *file;
1958
1959         for (language = 0;language < 2;language++)
1960         {
1961                 modeinfo = (language == 0 ? glslshadermodeinfo : hlslshadermodeinfo);
1962                 for (mode = 0;mode < SHADERMODE_COUNT;mode++)
1963                 {
1964                         // don't dump the same file multiple times (most or all shaders come from the same file)
1965                         for (dupe = mode - 1;dupe >= 0;dupe--)
1966                                 if (!strcmp(modeinfo[mode].filename, modeinfo[dupe].filename))
1967                                         break;
1968                         if (dupe >= 0)
1969                                 continue;
1970                         text = R_GetShaderText(modeinfo[mode].filename, false, true);
1971                         if (!text)
1972                                 continue;
1973                         file = FS_OpenRealFile(modeinfo[mode].filename, "w", false);
1974                         if (file)
1975                         {
1976                                 FS_Print(file, "/* The engine may define the following macros:\n");
1977                                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1978                                 for (i = 0;i < SHADERMODE_COUNT;i++)
1979                                         FS_Print(file, modeinfo[i].pretext);
1980                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1981                                         FS_Print(file, shaderpermutationinfo[i].pretext);
1982                                 FS_Print(file, "*/\n");
1983                                 FS_Print(file, text);
1984                                 FS_Close(file);
1985                                 Con_Printf("%s written\n", modeinfo[mode].filename);
1986                         }
1987                         else
1988                                 Con_Printf("failed to write to %s\n", modeinfo[mode].filename);
1989                         Mem_Free(text);
1990                 }
1991         }
1992 }
1993
1994 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1995 {
1996         unsigned int permutation = 0;
1997         if (r_trippy.integer && !notrippy)
1998                 permutation |= SHADERPERMUTATION_TRIPPY;
1999         permutation |= SHADERPERMUTATION_VIEWTINT;
2000         if (first)
2001                 permutation |= SHADERPERMUTATION_DIFFUSE;
2002         if (second)
2003                 permutation |= SHADERPERMUTATION_SPECULAR;
2004         if (texturemode == GL_MODULATE)
2005                 permutation |= SHADERPERMUTATION_COLORMAPPING;
2006         else if (texturemode == GL_ADD)
2007                 permutation |= SHADERPERMUTATION_GLOW;
2008         else if (texturemode == GL_DECAL)
2009                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2010         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
2011                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
2012         if (suppresstexalpha)
2013                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
2014         if (!second)
2015                 texturemode = GL_MODULATE;
2016         if (vid.allowalphatocoverage)
2017                 GL_AlphaToCoverage(false);
2018         switch (vid.renderpath)
2019         {
2020         case RENDERPATH_D3D9:
2021 #ifdef SUPPORTD3D
2022                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
2023                 R_Mesh_TexBind(GL20TU_FIRST , first );
2024                 R_Mesh_TexBind(GL20TU_SECOND, second);
2025                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
2026                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2027 #endif
2028                 break;
2029         case RENDERPATH_D3D10:
2030                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2031                 break;
2032         case RENDERPATH_D3D11:
2033                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2034                 break;
2035         case RENDERPATH_GL20:
2036         case RENDERPATH_GLES2:
2037                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
2038                 if (r_glsl_permutation->tex_Texture_First >= 0)
2039                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
2040                 if (r_glsl_permutation->tex_Texture_Second >= 0)
2041                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
2042                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
2043                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
2044                 break;
2045         case RENDERPATH_GL13:
2046         case RENDERPATH_GLES1:
2047                 R_Mesh_TexBind(0, first );
2048                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2049                 R_Mesh_TexMatrix(0, NULL);
2050                 R_Mesh_TexBind(1, second);
2051                 if (second)
2052                 {
2053                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
2054                         R_Mesh_TexMatrix(1, NULL);
2055                 }
2056                 break;
2057         case RENDERPATH_GL11:
2058                 R_Mesh_TexBind(0, first );
2059                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
2060                 R_Mesh_TexMatrix(0, NULL);
2061                 break;
2062         case RENDERPATH_SOFT:
2063                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
2064                 R_Mesh_TexBind(GL20TU_FIRST , first );
2065                 R_Mesh_TexBind(GL20TU_SECOND, second);
2066                 break;
2067         }
2068 }
2069
2070 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
2071 {
2072         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
2073 }
2074
2075 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb, qboolean skeletal)
2076 {
2077         unsigned int permutation = 0;
2078         if (r_trippy.integer && !notrippy)
2079                 permutation |= SHADERPERMUTATION_TRIPPY;
2080         if (depthrgb)
2081                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2082         if (skeletal)
2083                 permutation |= SHADERPERMUTATION_SKELETAL;
2084
2085         if (vid.allowalphatocoverage)
2086                 GL_AlphaToCoverage(false);
2087         switch (vid.renderpath)
2088         {
2089         case RENDERPATH_D3D9:
2090 #ifdef SUPPORTD3D
2091                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2092 #endif
2093                 break;
2094         case RENDERPATH_D3D10:
2095                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2096                 break;
2097         case RENDERPATH_D3D11:
2098                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2099                 break;
2100         case RENDERPATH_GL20:
2101         case RENDERPATH_GLES2:
2102                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2103 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2104                 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);
2105 #endif
2106                 break;
2107         case RENDERPATH_GL13:
2108         case RENDERPATH_GLES1:
2109                 R_Mesh_TexBind(0, 0);
2110                 R_Mesh_TexBind(1, 0);
2111                 break;
2112         case RENDERPATH_GL11:
2113                 R_Mesh_TexBind(0, 0);
2114                 break;
2115         case RENDERPATH_SOFT:
2116                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2117                 break;
2118         }
2119 }
2120
2121 extern qboolean r_shadow_usingdeferredprepass;
2122 extern rtexture_t *r_shadow_attenuationgradienttexture;
2123 extern rtexture_t *r_shadow_attenuation2dtexture;
2124 extern rtexture_t *r_shadow_attenuation3dtexture;
2125 extern qboolean r_shadow_usingshadowmap2d;
2126 extern qboolean r_shadow_usingshadowmaportho;
2127 extern float r_shadow_shadowmap_texturescale[2];
2128 extern float r_shadow_shadowmap_parameters[4];
2129 extern qboolean r_shadow_shadowmapvsdct;
2130 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2131 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2132 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2133 extern matrix4x4_t r_shadow_shadowmapmatrix;
2134 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2135 extern int r_shadow_prepass_width;
2136 extern int r_shadow_prepass_height;
2137 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2138 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2139 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2140 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2141
2142 #define BLENDFUNC_ALLOWS_COLORMOD      1
2143 #define BLENDFUNC_ALLOWS_FOG           2
2144 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2145 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2146 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2147 static int R_BlendFuncFlags(int src, int dst)
2148 {
2149         int r = 0;
2150
2151         // a blendfunc allows colormod if:
2152         // a) it can never keep the destination pixel invariant, or
2153         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2154         // this is to prevent unintended side effects from colormod
2155
2156         // a blendfunc allows fog if:
2157         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2158         // this is to prevent unintended side effects from fog
2159
2160         // these checks are the output of fogeval.pl
2161
2162         r |= BLENDFUNC_ALLOWS_COLORMOD;
2163         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2164         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2165         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2166         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2167         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2168         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2169         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2170         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2171         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2172         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2173         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2174         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2175         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2176         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2177         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2178         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2179         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2180         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2181         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2182         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2183         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2184
2185         return r;
2186 }
2187
2188 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)
2189 {
2190         // select a permutation of the lighting shader appropriate to this
2191         // combination of texture, entity, light source, and fogging, only use the
2192         // minimum features necessary to avoid wasting rendering time in the
2193         // fragment shader on features that are not being used
2194         unsigned int permutation = 0;
2195         unsigned int mode = 0;
2196         int blendfuncflags;
2197         static float dummy_colormod[3] = {1, 1, 1};
2198         float *colormod = rsurface.colormod;
2199         float m16f[16];
2200         matrix4x4_t tempmatrix;
2201         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2202         if (r_trippy.integer && !notrippy)
2203                 permutation |= SHADERPERMUTATION_TRIPPY;
2204         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2205                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2206         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_OCCLUDE)
2207                 permutation |= SHADERPERMUTATION_OCCLUDE;
2208         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2209                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2210         if (rsurfacepass == RSURFPASS_BACKGROUND)
2211         {
2212                 // distorted background
2213                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2214                 {
2215                         mode = SHADERMODE_WATER;
2216                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2217                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2218                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2219                         {
2220                                 // this is the right thing to do for wateralpha
2221                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2222                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2223                         }
2224                         else
2225                         {
2226                                 // this is the right thing to do for entity alpha
2227                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2228                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2229                         }
2230                 }
2231                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2232                 {
2233                         mode = SHADERMODE_REFRACTION;
2234                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2235                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2236                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2237                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2238                 }
2239                 else
2240                 {
2241                         mode = SHADERMODE_GENERIC;
2242                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2243                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2244                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2245                 }
2246                 if (vid.allowalphatocoverage)
2247                         GL_AlphaToCoverage(false);
2248         }
2249         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2250         {
2251                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2252                 {
2253                         switch(rsurface.texture->offsetmapping)
2254                         {
2255                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2256                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2257                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2258                         case OFFSETMAPPING_OFF: break;
2259                         }
2260                 }
2261                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2262                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2263                 // normalmap (deferred prepass), may use alpha test on diffuse
2264                 mode = SHADERMODE_DEFERREDGEOMETRY;
2265                 GL_BlendFunc(GL_ONE, GL_ZERO);
2266                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2267                 if (vid.allowalphatocoverage)
2268                         GL_AlphaToCoverage(false);
2269         }
2270         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2271         {
2272                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2273                 {
2274                         switch(rsurface.texture->offsetmapping)
2275                         {
2276                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2277                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2278                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2279                         case OFFSETMAPPING_OFF: break;
2280                         }
2281                 }
2282                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2283                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2284                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2285                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2286                 // light source
2287                 mode = SHADERMODE_LIGHTSOURCE;
2288                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2289                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2290                 if (diffusescale > 0)
2291                         permutation |= SHADERPERMUTATION_DIFFUSE;
2292                 if (specularscale > 0)
2293                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2294                 if (r_refdef.fogenabled)
2295                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2296                 if (rsurface.texture->colormapping)
2297                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2298                 if (r_shadow_usingshadowmap2d)
2299                 {
2300                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2301                         if(r_shadow_shadowmapvsdct)
2302                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2303
2304                         if (r_shadow_shadowmap2ddepthbuffer)
2305                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2306                 }
2307                 if (rsurface.texture->reflectmasktexture)
2308                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2309                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2310                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2311                 if (vid.allowalphatocoverage)
2312                         GL_AlphaToCoverage(false);
2313         }
2314         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2315         {
2316                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2317                 {
2318                         switch(rsurface.texture->offsetmapping)
2319                         {
2320                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2321                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2322                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2323                         case OFFSETMAPPING_OFF: break;
2324                         }
2325                 }
2326                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2327                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2328                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2329                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2330                 // unshaded geometry (fullbright or ambient model lighting)
2331                 mode = SHADERMODE_FLATCOLOR;
2332                 ambientscale = diffusescale = specularscale = 0;
2333                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2334                         permutation |= SHADERPERMUTATION_GLOW;
2335                 if (r_refdef.fogenabled)
2336                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2337                 if (rsurface.texture->colormapping)
2338                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2339                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2340                 {
2341                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2342                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2343
2344                         if (r_shadow_shadowmap2ddepthbuffer)
2345                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2346                 }
2347                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2348                         permutation |= SHADERPERMUTATION_REFLECTION;
2349                 if (rsurface.texture->reflectmasktexture)
2350                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2351                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2352                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2353                 // when using alphatocoverage, we don't need alphakill
2354                 if (vid.allowalphatocoverage)
2355                 {
2356                         if (r_transparent_alphatocoverage.integer)
2357                         {
2358                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2359                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2360                         }
2361                         else
2362                                 GL_AlphaToCoverage(false);
2363                 }
2364         }
2365         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2366         {
2367                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2368                 {
2369                         switch(rsurface.texture->offsetmapping)
2370                         {
2371                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2372                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2373                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2374                         case OFFSETMAPPING_OFF: break;
2375                         }
2376                 }
2377                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2378                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2379                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2380                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2381                 // directional model lighting
2382                 mode = SHADERMODE_LIGHTDIRECTION;
2383                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2384                         permutation |= SHADERPERMUTATION_GLOW;
2385                 permutation |= SHADERPERMUTATION_DIFFUSE;
2386                 if (specularscale > 0)
2387                         permutation |= SHADERPERMUTATION_SPECULAR;
2388                 if (r_refdef.fogenabled)
2389                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2390                 if (rsurface.texture->colormapping)
2391                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2392                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2393                 {
2394                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2395                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2396
2397                         if (r_shadow_shadowmap2ddepthbuffer)
2398                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2399                 }
2400                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2401                         permutation |= SHADERPERMUTATION_REFLECTION;
2402                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2403                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2404                 if (rsurface.texture->reflectmasktexture)
2405                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2406                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2407                 {
2408                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2409                         if (r_shadow_bouncegriddirectional)
2410                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2411                 }
2412                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2413                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2414                 // when using alphatocoverage, we don't need alphakill
2415                 if (vid.allowalphatocoverage)
2416                 {
2417                         if (r_transparent_alphatocoverage.integer)
2418                         {
2419                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2420                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2421                         }
2422                         else
2423                                 GL_AlphaToCoverage(false);
2424                 }
2425         }
2426         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2427         {
2428                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2429                 {
2430                         switch(rsurface.texture->offsetmapping)
2431                         {
2432                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2433                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2434                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2435                         case OFFSETMAPPING_OFF: break;
2436                         }
2437                 }
2438                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2439                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2440                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2441                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2442                 // ambient model lighting
2443                 mode = SHADERMODE_LIGHTDIRECTION;
2444                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2445                         permutation |= SHADERPERMUTATION_GLOW;
2446                 if (r_refdef.fogenabled)
2447                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2448                 if (rsurface.texture->colormapping)
2449                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2450                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2451                 {
2452                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2453                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2454
2455                         if (r_shadow_shadowmap2ddepthbuffer)
2456                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2457                 }
2458                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2459                         permutation |= SHADERPERMUTATION_REFLECTION;
2460                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2461                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2462                 if (rsurface.texture->reflectmasktexture)
2463                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2464                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2465                 {
2466                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2467                         if (r_shadow_bouncegriddirectional)
2468                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2469                 }
2470                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2471                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2472                 // when using alphatocoverage, we don't need alphakill
2473                 if (vid.allowalphatocoverage)
2474                 {
2475                         if (r_transparent_alphatocoverage.integer)
2476                         {
2477                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2478                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2479                         }
2480                         else
2481                                 GL_AlphaToCoverage(false);
2482                 }
2483         }
2484         else
2485         {
2486                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2487                 {
2488                         switch(rsurface.texture->offsetmapping)
2489                         {
2490                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2491                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2492                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2493                         case OFFSETMAPPING_OFF: break;
2494                         }
2495                 }
2496                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2497                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2498                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2499                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2500                 // lightmapped wall
2501                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2502                         permutation |= SHADERPERMUTATION_GLOW;
2503                 if (r_refdef.fogenabled)
2504                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2505                 if (rsurface.texture->colormapping)
2506                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2507                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2508                 {
2509                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2510                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2511
2512                         if (r_shadow_shadowmap2ddepthbuffer)
2513                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2514                 }
2515                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2516                         permutation |= SHADERPERMUTATION_REFLECTION;
2517                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2518                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2519                 if (rsurface.texture->reflectmasktexture)
2520                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2521                 if (FAKELIGHT_ENABLED)
2522                 {
2523                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2524                         mode = SHADERMODE_FAKELIGHT;
2525                         permutation |= SHADERPERMUTATION_DIFFUSE;
2526                         if (specularscale > 0)
2527                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2528                 }
2529                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2530                 {
2531                         // deluxemapping (light direction texture)
2532                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2533                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2534                         else
2535                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2536                         permutation |= SHADERPERMUTATION_DIFFUSE;
2537                         if (specularscale > 0)
2538                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2539                 }
2540                 else if (r_glsl_deluxemapping.integer >= 2)
2541                 {
2542                         // fake deluxemapping (uniform light direction in tangentspace)
2543                         if (rsurface.uselightmaptexture)
2544                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2545                         else
2546                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2547                         permutation |= SHADERPERMUTATION_DIFFUSE;
2548                         if (specularscale > 0)
2549                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2550                 }
2551                 else if (rsurface.uselightmaptexture)
2552                 {
2553                         // ordinary lightmapping (q1bsp, q3bsp)
2554                         mode = SHADERMODE_LIGHTMAP;
2555                 }
2556                 else
2557                 {
2558                         // ordinary vertex coloring (q3bsp)
2559                         mode = SHADERMODE_VERTEXCOLOR;
2560                 }
2561                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2562                 {
2563                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2564                         if (r_shadow_bouncegriddirectional)
2565                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2566                 }
2567                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2568                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2569                 // when using alphatocoverage, we don't need alphakill
2570                 if (vid.allowalphatocoverage)
2571                 {
2572                         if (r_transparent_alphatocoverage.integer)
2573                         {
2574                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2575                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2576                         }
2577                         else
2578                                 GL_AlphaToCoverage(false);
2579                 }
2580         }
2581         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2582                 colormod = dummy_colormod;
2583         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2584                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2585         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2586                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2587         switch(vid.renderpath)
2588         {
2589         case RENDERPATH_D3D9:
2590 #ifdef SUPPORTD3D
2591                 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);
2592                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2593                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2594                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2595                 if (mode == SHADERMODE_LIGHTSOURCE)
2596                 {
2597                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2598                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2599                 }
2600                 else
2601                 {
2602                         if (mode == SHADERMODE_LIGHTDIRECTION)
2603                         {
2604                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2605                         }
2606                 }
2607                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2608                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2609                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2610                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2611                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2612
2613                 if (mode == SHADERMODE_LIGHTSOURCE)
2614                 {
2615                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2616                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2617                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2618                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2619                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2620
2621                         // additive passes are only darkened by fog, not tinted
2622                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2623                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2624                 }
2625                 else
2626                 {
2627                         if (mode == SHADERMODE_FLATCOLOR)
2628                         {
2629                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2630                         }
2631                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2632                         {
2633                                 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]);
2634                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2635                                 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);
2636                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2637                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2638                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2639                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2640                         }
2641                         else
2642                         {
2643                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2644                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2645                                 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);
2646                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2647                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2648                         }
2649                         // additive passes are only darkened by fog, not tinted
2650                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2651                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2652                         else
2653                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2654                         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);
2655                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2656                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2657                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2658                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2659                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2660                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2661                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2662                         if (mode == SHADERMODE_WATER)
2663                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2664                 }
2665                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2666                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2667                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2668                 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));
2669                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2670                 if (rsurface.texture->pantstexture)
2671                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2672                 else
2673                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2674                 if (rsurface.texture->shirttexture)
2675                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2676                 else
2677                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2678                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2679                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2680                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2681                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2682                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2683                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2684                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2685                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2686                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2687                         );
2688                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2689                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2690                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2691                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2692
2693                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2694                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2695                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2696                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2697                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2698                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2699                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2700                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2701                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2702                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2703                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2704                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2705                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2706                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2707                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2708                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2709                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2710                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2711                 {
2712                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2713                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2714                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2715                 }
2716                 else
2717                 {
2718                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2719                 }
2720 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2721                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2722                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2723                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2724                 {
2725                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2726                         if (rsurface.rtlight)
2727                         {
2728                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2729                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2730                         }
2731                 }
2732 #endif
2733                 break;
2734         case RENDERPATH_D3D10:
2735                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2736                 break;
2737         case RENDERPATH_D3D11:
2738                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2739                 break;
2740         case RENDERPATH_GL20:
2741         case RENDERPATH_GLES2:
2742                 if (!vid.useinterleavedarrays)
2743                 {
2744                         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);
2745                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2746                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2747                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2748                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2749                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2750                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2751                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2752                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2753                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2754                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2755                 }
2756                 else
2757                 {
2758                         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);
2759                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmesh_vertexbuffer, rsurface.batchvertexmesh_bufferoffset);
2760                 }
2761                 // this has to be after RSurf_PrepareVerticesForBatch
2762                 if (rsurface.batchskeletaltransform3x4buffer)
2763                         permutation |= SHADERPERMUTATION_SKELETAL;
2764                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2765 #ifndef USE_GLES2 /* FIXME: GLES3 only */
2766                 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);
2767 #endif
2768                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2769                 if (mode == SHADERMODE_LIGHTSOURCE)
2770                 {
2771                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2772                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2773                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2774                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2775                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2776                         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);
2777         
2778                         // additive passes are only darkened by fog, not tinted
2779                         if (r_glsl_permutation->loc_FogColor >= 0)
2780                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2781                         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);
2782                 }
2783                 else
2784                 {
2785                         if (mode == SHADERMODE_FLATCOLOR)
2786                         {
2787                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2788                         }
2789                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2790                         {
2791                                 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]);
2792                                 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]);
2793                                 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);
2794                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2795                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2796                                 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]);
2797                                 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]);
2798                         }
2799                         else
2800                         {
2801                                 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]);
2802                                 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]);
2803                                 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);
2804                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2805                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2806                         }
2807                         // additive passes are only darkened by fog, not tinted
2808                         if (r_glsl_permutation->loc_FogColor >= 0)
2809                         {
2810                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2811                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2812                                 else
2813                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2814                         }
2815                         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);
2816                         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]);
2817                         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]);
2818                         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]);
2819                         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]);
2820                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2821                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2822                         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);
2823                         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]);
2824                 }
2825                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2826                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2827                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2828                 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]);
2829                 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]);
2830
2831                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2832                 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));
2833                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2834                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2835                 {
2836                         if (rsurface.texture->pantstexture)
2837                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2838                         else
2839                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2840                 }
2841                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2842                 {
2843                         if (rsurface.texture->shirttexture)
2844                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2845                         else
2846                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2847                 }
2848                 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]);
2849                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2850                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2851                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2852                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2853                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2854                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2855                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2856                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2857                         );
2858                 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);
2859                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2860                 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]);
2861                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2862                 if (r_glsl_permutation->loc_BounceGridMatrix >= 0) {Matrix4x4_Concat(&tempmatrix, &r_shadow_bouncegridmatrix, &rsurface.matrix);Matrix4x4_ToArrayFloatGL(&tempmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BounceGridMatrix, 1, false, m16f);}
2863                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2864
2865                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2866                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2867                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2868                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2869                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2870                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2871                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2872                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2873                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2874                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2875                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2876                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2877                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2878                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2879                 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);
2880                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2881                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2882                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2883                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2884                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2885                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2886                 {
2887                         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);
2888                         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);
2889                         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);
2890                 }
2891                 else
2892                 {
2893                         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);
2894                 }
2895                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2896                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2897                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2898                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2899                 {
2900                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2901                         if (rsurface.rtlight)
2902                         {
2903                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2904                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2905                         }
2906                 }
2907                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2908                 CHECKGLERROR
2909                 break;
2910         case RENDERPATH_GL11:
2911         case RENDERPATH_GL13:
2912         case RENDERPATH_GLES1:
2913                 break;
2914         case RENDERPATH_SOFT:
2915                 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);
2916                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2917                 R_SetupShader_SetPermutationSoft(mode, permutation);
2918                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2919                 if (mode == SHADERMODE_LIGHTSOURCE)
2920                 {
2921                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2922                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2923                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2924                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2925                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2926                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2927         
2928                         // additive passes are only darkened by fog, not tinted
2929                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2930                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2931                 }
2932                 else
2933                 {
2934                         if (mode == SHADERMODE_FLATCOLOR)
2935                         {
2936                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2937                         }
2938                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2939                         {
2940                                 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]);
2941                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2942                                 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);
2943                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2944                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2945                                 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]);
2946                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2947                         }
2948                         else
2949                         {
2950                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2951                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2952                                 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);
2953                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2954                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2955                         }
2956                         // additive passes are only darkened by fog, not tinted
2957                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2958                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2959                         else
2960                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2961                         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);
2962                         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]);
2963                         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]);
2964                         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]);
2965                         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]);
2966                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2967                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2968                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2969                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2970                 }
2971                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2972                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2973                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2974                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2975                 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]);
2976
2977                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2978                 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));
2979                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2980                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2981                 {
2982                         if (rsurface.texture->pantstexture)
2983                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2984                         else
2985                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2986                 }
2987                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2988                 {
2989                         if (rsurface.texture->shirttexture)
2990                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2991                         else
2992                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2993                 }
2994                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2995                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2996                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2997                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2998                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2999                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
3000                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3001                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
3002                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
3003                         );
3004                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
3005                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
3006                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3007                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3008
3009                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
3010                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
3011                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
3012                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
3013                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
3014                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
3015                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
3016                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
3017                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
3018                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
3019                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
3020                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
3021                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
3022                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
3023                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
3024                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
3025                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
3026                 if (rsurfacepass == RSURFPASS_BACKGROUND)
3027                 {
3028                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
3029                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
3030                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3031                 }
3032                 else
3033                 {
3034                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
3035                 }
3036 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
3037                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
3038                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
3039                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
3040                 {
3041                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
3042                         if (rsurface.rtlight)
3043                         {
3044                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
3045                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
3046                         }
3047                 }
3048                 break;
3049         }
3050 }
3051
3052 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
3053 {
3054         // select a permutation of the lighting shader appropriate to this
3055         // combination of texture, entity, light source, and fogging, only use the
3056         // minimum features necessary to avoid wasting rendering time in the
3057         // fragment shader on features that are not being used
3058         unsigned int permutation = 0;
3059         unsigned int mode = 0;
3060         const float *lightcolorbase = rtlight->currentcolor;
3061         float ambientscale = rtlight->ambientscale;
3062         float diffusescale = rtlight->diffusescale;
3063         float specularscale = rtlight->specularscale;
3064         // this is the location of the light in view space
3065         vec3_t viewlightorigin;
3066         // this transforms from view space (camera) to light space (cubemap)
3067         matrix4x4_t viewtolight;
3068         matrix4x4_t lighttoview;
3069         float viewtolight16f[16];
3070         // light source
3071         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3072         if (rtlight->currentcubemap != r_texture_whitecube)
3073                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3074         if (diffusescale > 0)
3075                 permutation |= SHADERPERMUTATION_DIFFUSE;
3076         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3077                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3078         if (r_shadow_usingshadowmap2d)
3079         {
3080                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3081                 if (r_shadow_shadowmapvsdct)
3082                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3083
3084                 if (r_shadow_shadowmap2ddepthbuffer)
3085                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3086         }
3087         if (vid.allowalphatocoverage)
3088                 GL_AlphaToCoverage(false);
3089         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3090         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3091         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3092         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3093         switch(vid.renderpath)
3094         {
3095         case RENDERPATH_D3D9:
3096 #ifdef SUPPORTD3D
3097                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3098                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3099                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3100                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3101                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3102                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3103                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3104                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3105                 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);
3106                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3107                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3108
3109                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3110                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3111                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3112                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3113                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3114 #endif
3115                 break;
3116         case RENDERPATH_D3D10:
3117                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3118                 break;
3119         case RENDERPATH_D3D11:
3120                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3121                 break;
3122         case RENDERPATH_GL20:
3123         case RENDERPATH_GLES2:
3124                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3125                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3126                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3127                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3128                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3129                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3130                 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]);
3131                 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]);
3132                 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);
3133                 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]);
3134                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3135
3136                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3137                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3138                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3139                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3140                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3141                 break;
3142         case RENDERPATH_GL11:
3143         case RENDERPATH_GL13:
3144         case RENDERPATH_GLES1:
3145                 break;
3146         case RENDERPATH_SOFT:
3147                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3148                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3149                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3150                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3151                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3152                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3153                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3154                 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]);
3155                 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);
3156                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3157                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3158
3159                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3160                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3161                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3162                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3163                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3164                 break;
3165         }
3166 }
3167
3168 #define SKINFRAME_HASH 1024
3169
3170 typedef struct
3171 {
3172         unsigned int loadsequence; // incremented each level change
3173         memexpandablearray_t array;
3174         skinframe_t *hash[SKINFRAME_HASH];
3175 }
3176 r_skinframe_t;
3177 r_skinframe_t r_skinframe;
3178
3179 void R_SkinFrame_PrepareForPurge(void)
3180 {
3181         r_skinframe.loadsequence++;
3182         // wrap it without hitting zero
3183         if (r_skinframe.loadsequence >= 200)
3184                 r_skinframe.loadsequence = 1;
3185 }
3186
3187 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3188 {
3189         if (!skinframe)
3190                 return;
3191         // mark the skinframe as used for the purging code
3192         skinframe->loadsequence = r_skinframe.loadsequence;
3193 }
3194
3195 void R_SkinFrame_Purge(void)
3196 {
3197         int i;
3198         skinframe_t *s;
3199         for (i = 0;i < SKINFRAME_HASH;i++)
3200         {
3201                 for (s = r_skinframe.hash[i];s;s = s->next)
3202                 {
3203                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3204                         {
3205                                 if (s->merged == s->base)
3206                                         s->merged = NULL;
3207                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3208                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3209                                 R_PurgeTexture(s->merged);s->merged = NULL;
3210                                 R_PurgeTexture(s->base  );s->base   = NULL;
3211                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3212                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3213                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3214                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3215                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3216                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3217                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3218                                 s->loadsequence = 0;
3219                         }
3220                 }
3221         }
3222 }
3223
3224 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3225         skinframe_t *item;
3226         char basename[MAX_QPATH];
3227
3228         Image_StripImageExtension(name, basename, sizeof(basename));
3229
3230         if( last == NULL ) {
3231                 int hashindex;
3232                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3233                 item = r_skinframe.hash[hashindex];
3234         } else {
3235                 item = last->next;
3236         }
3237
3238         // linearly search through the hash bucket
3239         for( ; item ; item = item->next ) {
3240                 if( !strcmp( item->basename, basename ) ) {
3241                         return item;
3242                 }
3243         }
3244         return NULL;
3245 }
3246
3247 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3248 {
3249         skinframe_t *item;
3250         int hashindex;
3251         char basename[MAX_QPATH];
3252
3253         Image_StripImageExtension(name, basename, sizeof(basename));
3254
3255         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3256         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3257                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3258                         break;
3259
3260         if (!item) {
3261                 rtexture_t *dyntexture;
3262                 // check whether its a dynamic texture
3263                 dyntexture = CL_GetDynTexture( basename );
3264                 if (!add && !dyntexture)
3265                         return NULL;
3266                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3267                 memset(item, 0, sizeof(*item));
3268                 strlcpy(item->basename, basename, sizeof(item->basename));
3269                 item->base = dyntexture; // either NULL or dyntexture handle
3270                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3271                 item->comparewidth = comparewidth;
3272                 item->compareheight = compareheight;
3273                 item->comparecrc = comparecrc;
3274                 item->next = r_skinframe.hash[hashindex];
3275                 r_skinframe.hash[hashindex] = item;
3276         }
3277         else if (textureflags & TEXF_FORCE_RELOAD)
3278         {
3279                 rtexture_t *dyntexture;
3280                 // check whether its a dynamic texture
3281                 dyntexture = CL_GetDynTexture( basename );
3282                 if (!add && !dyntexture)
3283                         return NULL;
3284                 if (item->merged == item->base)
3285                         item->merged = NULL;
3286                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3287                 R_PurgeTexture(item->stain );item->stain  = NULL;
3288                 R_PurgeTexture(item->merged);item->merged = NULL;
3289                 R_PurgeTexture(item->base  );item->base   = NULL;
3290                 R_PurgeTexture(item->pants );item->pants  = NULL;
3291                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3292                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3293                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3294                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3295                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3296         R_PurgeTexture(item->reflect);item->reflect = NULL;
3297                 item->loadsequence = 0;
3298         }
3299         else if( item->base == NULL )
3300         {
3301                 rtexture_t *dyntexture;
3302                 // check whether its a dynamic texture
3303                 // 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]
3304                 dyntexture = CL_GetDynTexture( basename );
3305                 item->base = dyntexture; // either NULL or dyntexture handle
3306         }
3307
3308         R_SkinFrame_MarkUsed(item);
3309         return item;
3310 }
3311
3312 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3313         { \
3314                 unsigned long long avgcolor[5], wsum; \
3315                 int pix, comp, w; \
3316                 avgcolor[0] = 0; \
3317                 avgcolor[1] = 0; \
3318                 avgcolor[2] = 0; \
3319                 avgcolor[3] = 0; \
3320                 avgcolor[4] = 0; \
3321                 wsum = 0; \
3322                 for(pix = 0; pix < cnt; ++pix) \
3323                 { \
3324                         w = 0; \
3325                         for(comp = 0; comp < 3; ++comp) \
3326                                 w += getpixel; \
3327                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3328                         { \
3329                                 ++wsum; \
3330                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3331                                 w = getpixel; \
3332                                 for(comp = 0; comp < 3; ++comp) \
3333                                         avgcolor[comp] += getpixel * w; \
3334                                 avgcolor[3] += w; \
3335                         } \
3336                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3337                         avgcolor[4] += getpixel; \
3338                 } \
3339                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3340                         avgcolor[3] = 1; \
3341                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3342                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3343                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3344                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3345         }
3346
3347 extern cvar_t gl_picmip;
3348 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3349 {
3350         int j;
3351         unsigned char *pixels;
3352         unsigned char *bumppixels;
3353         unsigned char *basepixels = NULL;
3354         int basepixels_width = 0;
3355         int basepixels_height = 0;
3356         skinframe_t *skinframe;
3357         rtexture_t *ddsbase = NULL;
3358         qboolean ddshasalpha = false;
3359         float ddsavgcolor[4];
3360         char basename[MAX_QPATH];
3361         int miplevel = R_PicmipForFlags(textureflags);
3362         int savemiplevel = miplevel;
3363         int mymiplevel;
3364         char vabuf[1024];
3365
3366         if (cls.state == ca_dedicated)
3367                 return NULL;
3368
3369         // return an existing skinframe if already loaded
3370         // if loading of the first image fails, don't make a new skinframe as it
3371         // would cause all future lookups of this to be missing
3372         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3373         if (skinframe && skinframe->base)
3374                 return skinframe;
3375
3376         Image_StripImageExtension(name, basename, sizeof(basename));
3377
3378         // check for DDS texture file first
3379         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3380         {
3381                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3382                 if (basepixels == NULL)
3383                         return NULL;
3384         }
3385
3386         // FIXME handle miplevel
3387
3388         if (developer_loading.integer)
3389                 Con_Printf("loading skin \"%s\"\n", name);
3390
3391         // we've got some pixels to store, so really allocate this new texture now
3392         if (!skinframe)
3393                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3394         textureflags &= ~TEXF_FORCE_RELOAD;
3395         skinframe->stain = NULL;
3396         skinframe->merged = NULL;
3397         skinframe->base = NULL;
3398         skinframe->pants = NULL;
3399         skinframe->shirt = NULL;
3400         skinframe->nmap = NULL;
3401         skinframe->gloss = NULL;
3402         skinframe->glow = NULL;
3403         skinframe->fog = NULL;
3404         skinframe->reflect = NULL;
3405         skinframe->hasalpha = false;
3406         // we could store the q2animname here too
3407
3408         if (ddsbase)
3409         {
3410                 skinframe->base = ddsbase;
3411                 skinframe->hasalpha = ddshasalpha;
3412                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3413                 if (r_loadfog && skinframe->hasalpha)
3414                         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);
3415                 //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]);
3416         }
3417         else
3418         {
3419                 basepixels_width = image_width;
3420                 basepixels_height = image_height;
3421                 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);
3422                 if (textureflags & TEXF_ALPHA)
3423                 {
3424                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3425                         {
3426                                 if (basepixels[j] < 255)
3427                                 {
3428                                         skinframe->hasalpha = true;
3429                                         break;
3430                                 }
3431                         }
3432                         if (r_loadfog && skinframe->hasalpha)
3433                         {
3434                                 // has transparent pixels
3435                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3436                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3437                                 {
3438                                         pixels[j+0] = 255;
3439                                         pixels[j+1] = 255;
3440                                         pixels[j+2] = 255;
3441                                         pixels[j+3] = basepixels[j+3];
3442                                 }
3443                                 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);
3444                                 Mem_Free(pixels);
3445                         }
3446                 }
3447                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3448 #ifndef USE_GLES2
3449                 //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]);
3450                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3451                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3452                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3453                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3454 #endif
3455         }
3456
3457         if (r_loaddds)
3458         {
3459                 mymiplevel = savemiplevel;
3460                 if (r_loadnormalmap)
3461                         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);
3462                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3463                 if (r_loadgloss)
3464                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3465                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3466                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3467                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3468         }
3469
3470         // _norm is the name used by tenebrae and has been adopted as standard
3471         if (r_loadnormalmap && skinframe->nmap == NULL)
3472         {
3473                 mymiplevel = savemiplevel;
3474                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3475                 {
3476                         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);
3477                         Mem_Free(pixels);
3478                         pixels = NULL;
3479                 }
3480                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3481                 {
3482                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3483                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3484                         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);
3485                         Mem_Free(pixels);
3486                         Mem_Free(bumppixels);
3487                 }
3488                 else if (r_shadow_bumpscale_basetexture.value > 0)
3489                 {
3490                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3491                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3492                         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);
3493                         Mem_Free(pixels);
3494                 }
3495 #ifndef USE_GLES2
3496                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3497                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3498 #endif
3499         }
3500
3501         // _luma is supported only for tenebrae compatibility
3502         // _glow is the preferred name
3503         mymiplevel = savemiplevel;
3504         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))))
3505         {
3506                 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);
3507 #ifndef USE_GLES2
3508                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3509                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3510 #endif
3511                 Mem_Free(pixels);pixels = NULL;
3512         }
3513
3514         mymiplevel = savemiplevel;
3515         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3516         {
3517                 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);
3518 #ifndef USE_GLES2
3519                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3520                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3521 #endif
3522                 Mem_Free(pixels);
3523                 pixels = NULL;
3524         }
3525
3526         mymiplevel = savemiplevel;
3527         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3528         {
3529                 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);
3530 #ifndef USE_GLES2
3531                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3532                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3533 #endif
3534                 Mem_Free(pixels);
3535                 pixels = NULL;
3536         }
3537
3538         mymiplevel = savemiplevel;
3539         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3540         {
3541                 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);
3542 #ifndef USE_GLES2
3543                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3544                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.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->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3552         {
3553                 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);
3554 #ifndef USE_GLES2
3555                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3556                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3557 #endif
3558                 Mem_Free(pixels);
3559                 pixels = NULL;
3560         }
3561
3562         if (basepixels)
3563                 Mem_Free(basepixels);
3564
3565         return skinframe;
3566 }
3567
3568 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3569 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3570 {
3571         int i;
3572         unsigned char *temp1, *temp2;
3573         skinframe_t *skinframe;
3574         char vabuf[1024];
3575
3576         if (cls.state == ca_dedicated)
3577                 return NULL;
3578
3579         // if already loaded just return it, otherwise make a new skinframe
3580         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3581         if (skinframe->base)
3582                 return skinframe;
3583         textureflags &= ~TEXF_FORCE_RELOAD;
3584
3585         skinframe->stain = NULL;
3586         skinframe->merged = NULL;
3587         skinframe->base = NULL;
3588         skinframe->pants = NULL;
3589         skinframe->shirt = NULL;
3590         skinframe->nmap = NULL;
3591         skinframe->gloss = NULL;
3592         skinframe->glow = NULL;
3593         skinframe->fog = NULL;
3594         skinframe->reflect = NULL;
3595         skinframe->hasalpha = false;
3596
3597         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3598         if (!skindata)
3599                 return NULL;
3600
3601         if (developer_loading.integer)
3602                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3603
3604         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3605         {
3606                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3607                 temp2 = temp1 + width * height * 4;
3608                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3609                 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);
3610                 Mem_Free(temp1);
3611         }
3612         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3613         if (textureflags & TEXF_ALPHA)
3614         {
3615                 for (i = 3;i < width * height * 4;i += 4)
3616                 {
3617                         if (skindata[i] < 255)
3618                         {
3619                                 skinframe->hasalpha = true;
3620                                 break;
3621                         }
3622                 }
3623                 if (r_loadfog && skinframe->hasalpha)
3624                 {
3625                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3626                         memcpy(fogpixels, skindata, width * height * 4);
3627                         for (i = 0;i < width * height * 4;i += 4)
3628                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3629                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3630                         Mem_Free(fogpixels);
3631                 }
3632         }
3633
3634         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3635         //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]);
3636
3637         return skinframe;
3638 }
3639
3640 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3641 {
3642         int i;
3643         int featuresmask;
3644         skinframe_t *skinframe;
3645
3646         if (cls.state == ca_dedicated)
3647                 return NULL;
3648
3649         // if already loaded just return it, otherwise make a new skinframe
3650         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3651         if (skinframe->base)
3652                 return skinframe;
3653         //textureflags &= ~TEXF_FORCE_RELOAD;
3654
3655         skinframe->stain = NULL;
3656         skinframe->merged = NULL;
3657         skinframe->base = NULL;
3658         skinframe->pants = NULL;
3659         skinframe->shirt = NULL;
3660         skinframe->nmap = NULL;
3661         skinframe->gloss = NULL;
3662         skinframe->glow = NULL;
3663         skinframe->fog = NULL;
3664         skinframe->reflect = NULL;
3665         skinframe->hasalpha = false;
3666
3667         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3668         if (!skindata)
3669                 return NULL;
3670
3671         if (developer_loading.integer)
3672                 Con_Printf("loading quake skin \"%s\"\n", name);
3673
3674         // 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)
3675         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3676         memcpy(skinframe->qpixels, skindata, width*height);
3677         skinframe->qwidth = width;
3678         skinframe->qheight = height;
3679
3680         featuresmask = 0;
3681         for (i = 0;i < width * height;i++)
3682                 featuresmask |= palette_featureflags[skindata[i]];
3683
3684         skinframe->hasalpha = false;
3685         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3686         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3687         skinframe->qgeneratemerged = true;
3688         skinframe->qgeneratebase = skinframe->qhascolormapping;
3689         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3690
3691         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3692         //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]);
3693
3694         return skinframe;
3695 }
3696
3697 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3698 {
3699         int width;
3700         int height;
3701         unsigned char *skindata;
3702         char vabuf[1024];
3703
3704         if (!skinframe->qpixels)
3705                 return;
3706
3707         if (!skinframe->qhascolormapping)
3708                 colormapped = false;
3709
3710         if (colormapped)
3711         {
3712                 if (!skinframe->qgeneratebase)
3713                         return;
3714         }
3715         else
3716         {
3717                 if (!skinframe->qgeneratemerged)
3718                         return;
3719         }
3720
3721         width = skinframe->qwidth;
3722         height = skinframe->qheight;
3723         skindata = skinframe->qpixels;
3724
3725         if (skinframe->qgeneratenmap)
3726         {
3727                 unsigned char *temp1, *temp2;
3728                 skinframe->qgeneratenmap = false;
3729                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3730                 temp2 = temp1 + width * height * 4;
3731                 // use either a custom palette or the quake palette
3732                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3733                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3734                 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);
3735                 Mem_Free(temp1);
3736         }
3737
3738         if (skinframe->qgenerateglow)
3739         {
3740                 skinframe->qgenerateglow = false;
3741                 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
3742         }
3743
3744         if (colormapped)
3745         {
3746                 skinframe->qgeneratebase = false;
3747                 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);
3748                 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);
3749                 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);
3750         }
3751         else
3752         {
3753                 skinframe->qgeneratemerged = false;
3754                 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);
3755         }
3756
3757         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3758         {
3759                 Mem_Free(skinframe->qpixels);
3760                 skinframe->qpixels = NULL;
3761         }
3762 }
3763
3764 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)
3765 {
3766         int i;
3767         skinframe_t *skinframe;
3768         char vabuf[1024];
3769
3770         if (cls.state == ca_dedicated)
3771                 return NULL;
3772
3773         // if already loaded just return it, otherwise make a new skinframe
3774         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3775         if (skinframe->base)
3776                 return skinframe;
3777         textureflags &= ~TEXF_FORCE_RELOAD;
3778
3779         skinframe->stain = NULL;
3780         skinframe->merged = NULL;
3781         skinframe->base = NULL;
3782         skinframe->pants = NULL;
3783         skinframe->shirt = NULL;
3784         skinframe->nmap = NULL;
3785         skinframe->gloss = NULL;
3786         skinframe->glow = NULL;
3787         skinframe->fog = NULL;
3788         skinframe->reflect = NULL;
3789         skinframe->hasalpha = false;
3790
3791         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3792         if (!skindata)
3793                 return NULL;
3794
3795         if (developer_loading.integer)
3796                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3797
3798         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3799         if (textureflags & TEXF_ALPHA)
3800         {
3801                 for (i = 0;i < width * height;i++)
3802                 {
3803                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3804                         {
3805                                 skinframe->hasalpha = true;
3806                                 break;
3807                         }
3808                 }
3809                 if (r_loadfog && skinframe->hasalpha)
3810                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3811         }
3812
3813         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3814         //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]);
3815
3816         return skinframe;
3817 }
3818
3819 skinframe_t *R_SkinFrame_LoadMissing(void)
3820 {
3821         skinframe_t *skinframe;
3822
3823         if (cls.state == ca_dedicated)
3824                 return NULL;
3825
3826         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3827         skinframe->stain = NULL;
3828         skinframe->merged = NULL;
3829         skinframe->base = NULL;
3830         skinframe->pants = NULL;
3831         skinframe->shirt = NULL;
3832         skinframe->nmap = NULL;
3833         skinframe->gloss = NULL;
3834         skinframe->glow = NULL;
3835         skinframe->fog = NULL;
3836         skinframe->reflect = NULL;
3837         skinframe->hasalpha = false;
3838
3839         skinframe->avgcolor[0] = rand() / RAND_MAX;
3840         skinframe->avgcolor[1] = rand() / RAND_MAX;
3841         skinframe->avgcolor[2] = rand() / RAND_MAX;
3842         skinframe->avgcolor[3] = 1;
3843
3844         return skinframe;
3845 }
3846
3847 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3848 typedef struct suffixinfo_s
3849 {
3850         const char *suffix;
3851         qboolean flipx, flipy, flipdiagonal;
3852 }
3853 suffixinfo_t;
3854 static suffixinfo_t suffix[3][6] =
3855 {
3856         {
3857                 {"px",   false, false, false},
3858                 {"nx",   false, false, false},
3859                 {"py",   false, false, false},
3860                 {"ny",   false, false, false},
3861                 {"pz",   false, false, false},
3862                 {"nz",   false, false, false}
3863         },
3864         {
3865                 {"posx", false, false, false},
3866                 {"negx", false, false, false},
3867                 {"posy", false, false, false},
3868                 {"negy", false, false, false},
3869                 {"posz", false, false, false},
3870                 {"negz", false, false, false}
3871         },
3872         {
3873                 {"rt",    true, false,  true},
3874                 {"lf",   false,  true,  true},
3875                 {"ft",    true,  true, false},
3876                 {"bk",   false, false, false},
3877                 {"up",    true, false,  true},
3878                 {"dn",    true, false,  true}
3879         }
3880 };
3881
3882 static int componentorder[4] = {0, 1, 2, 3};
3883
3884 static rtexture_t *R_LoadCubemap(const char *basename)
3885 {
3886         int i, j, cubemapsize;
3887         unsigned char *cubemappixels, *image_buffer;
3888         rtexture_t *cubemaptexture;
3889         char name[256];
3890         // must start 0 so the first loadimagepixels has no requested width/height
3891         cubemapsize = 0;
3892         cubemappixels = NULL;
3893         cubemaptexture = NULL;
3894         // keep trying different suffix groups (posx, px, rt) until one loads
3895         for (j = 0;j < 3 && !cubemappixels;j++)
3896         {
3897                 // load the 6 images in the suffix group
3898                 for (i = 0;i < 6;i++)
3899                 {
3900                         // generate an image name based on the base and and suffix
3901                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3902                         // load it
3903                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3904                         {
3905                                 // an image loaded, make sure width and height are equal
3906                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3907                                 {
3908                                         // if this is the first image to load successfully, allocate the cubemap memory
3909                                         if (!cubemappixels && image_width >= 1)
3910                                         {
3911                                                 cubemapsize = image_width;
3912                                                 // note this clears to black, so unavailable sides are black
3913                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3914                                         }
3915                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3916                                         if (cubemappixels)
3917                                                 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);
3918                                 }
3919                                 else
3920                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3921                                 // free the image
3922                                 Mem_Free(image_buffer);
3923                         }
3924                 }
3925         }
3926         // if a cubemap loaded, upload it
3927         if (cubemappixels)
3928         {
3929                 if (developer_loading.integer)
3930                         Con_Printf("loading cubemap \"%s\"\n", basename);
3931
3932                 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);
3933                 Mem_Free(cubemappixels);
3934         }
3935         else
3936         {
3937                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3938                 if (developer_loading.integer)
3939                 {
3940                         Con_Printf("(tried tried images ");
3941                         for (j = 0;j < 3;j++)
3942                                 for (i = 0;i < 6;i++)
3943                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3944                         Con_Print(" and was unable to find any of them).\n");
3945                 }
3946         }
3947         return cubemaptexture;
3948 }
3949
3950 rtexture_t *R_GetCubemap(const char *basename)
3951 {
3952         int i;
3953         for (i = 0;i < r_texture_numcubemaps;i++)
3954                 if (r_texture_cubemaps[i] != NULL)
3955                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3956                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3957         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3958                 return r_texture_whitecube;
3959         r_texture_numcubemaps++;
3960         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3961         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3962         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3963         return r_texture_cubemaps[i]->texture;
3964 }
3965
3966 static void R_Main_FreeViewCache(void)
3967 {
3968         if (r_refdef.viewcache.entityvisible)
3969                 Mem_Free(r_refdef.viewcache.entityvisible);
3970         if (r_refdef.viewcache.world_pvsbits)
3971                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3972         if (r_refdef.viewcache.world_leafvisible)
3973                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3974         if (r_refdef.viewcache.world_surfacevisible)
3975                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3976         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3977 }
3978
3979 static void R_Main_ResizeViewCache(void)
3980 {
3981         int numentities = r_refdef.scene.numentities;
3982         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3983         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3984         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3985         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3986         if (r_refdef.viewcache.maxentities < numentities)
3987         {
3988                 r_refdef.viewcache.maxentities = numentities;
3989                 if (r_refdef.viewcache.entityvisible)
3990                         Mem_Free(r_refdef.viewcache.entityvisible);
3991                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3992         }
3993         if (r_refdef.viewcache.world_numclusters != numclusters)
3994         {
3995                 r_refdef.viewcache.world_numclusters = numclusters;
3996                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3997                 if (r_refdef.viewcache.world_pvsbits)
3998                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3999                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
4000         }
4001         if (r_refdef.viewcache.world_numleafs != numleafs)
4002         {
4003                 r_refdef.viewcache.world_numleafs = numleafs;
4004                 if (r_refdef.viewcache.world_leafvisible)
4005                         Mem_Free(r_refdef.viewcache.world_leafvisible);
4006                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
4007         }
4008         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
4009         {
4010                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
4011                 if (r_refdef.viewcache.world_surfacevisible)
4012                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
4013                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
4014         }
4015 }
4016
4017 extern rtexture_t *loadingscreentexture;
4018 static void gl_main_start(void)
4019 {
4020         loadingscreentexture = NULL;
4021         r_texture_blanknormalmap = NULL;
4022         r_texture_white = NULL;
4023         r_texture_grey128 = NULL;
4024         r_texture_black = NULL;
4025         r_texture_whitecube = NULL;
4026         r_texture_normalizationcube = NULL;
4027         r_texture_fogattenuation = NULL;
4028         r_texture_fogheighttexture = NULL;
4029         r_texture_gammaramps = NULL;
4030         r_texture_numcubemaps = 0;
4031         r_uniformbufferalignment = 32;
4032
4033         r_loaddds = r_texture_dds_load.integer != 0;
4034         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
4035
4036         switch(vid.renderpath)
4037         {
4038         case RENDERPATH_GL20:
4039         case RENDERPATH_D3D9:
4040         case RENDERPATH_D3D10:
4041         case RENDERPATH_D3D11:
4042         case RENDERPATH_SOFT:
4043         case RENDERPATH_GLES2:
4044                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4045                 Cvar_SetValueQuick(&gl_combine, 1);
4046                 Cvar_SetValueQuick(&r_glsl, 1);
4047                 r_loadnormalmap = true;
4048                 r_loadgloss = true;
4049                 r_loadfog = false;
4050 #ifdef GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT
4051                 if (vid.support.arb_uniform_buffer_object)
4052                         qglGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &r_uniformbufferalignment);
4053 #endif
4054                         break;
4055         case RENDERPATH_GL13:
4056         case RENDERPATH_GLES1:
4057                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4058                 Cvar_SetValueQuick(&gl_combine, 1);
4059                 Cvar_SetValueQuick(&r_glsl, 0);
4060                 r_loadnormalmap = false;
4061                 r_loadgloss = false;
4062                 r_loadfog = true;
4063                 break;
4064         case RENDERPATH_GL11:
4065                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4066                 Cvar_SetValueQuick(&gl_combine, 0);
4067                 Cvar_SetValueQuick(&r_glsl, 0);
4068                 r_loadnormalmap = false;
4069                 r_loadgloss = false;
4070                 r_loadfog = true;
4071                 break;
4072         }
4073
4074         R_AnimCache_Free();
4075         R_FrameData_Reset();
4076         R_BufferData_Reset();
4077
4078         r_numqueries = 0;
4079         r_maxqueries = 0;
4080         memset(r_queries, 0, sizeof(r_queries));
4081
4082         r_qwskincache = NULL;
4083         r_qwskincache_size = 0;
4084
4085         // due to caching of texture_t references, the collision cache must be reset
4086         Collision_Cache_Reset(true);
4087
4088         // set up r_skinframe loading system for textures
4089         memset(&r_skinframe, 0, sizeof(r_skinframe));
4090         r_skinframe.loadsequence = 1;
4091         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4092
4093         r_main_texturepool = R_AllocTexturePool();
4094         R_BuildBlankTextures();
4095         R_BuildNoTexture();
4096         if (vid.support.arb_texture_cube_map)
4097         {
4098                 R_BuildWhiteCube();
4099                 R_BuildNormalizationCube();
4100         }
4101         r_texture_fogattenuation = NULL;
4102         r_texture_fogheighttexture = NULL;
4103         r_texture_gammaramps = NULL;
4104         //r_texture_fogintensity = NULL;
4105         memset(&r_fb, 0, sizeof(r_fb));
4106         r_glsl_permutation = NULL;
4107         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4108         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4109         glslshaderstring = NULL;
4110 #ifdef SUPPORTD3D
4111         r_hlsl_permutation = NULL;
4112         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4113         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4114 #endif
4115         hlslshaderstring = NULL;
4116         memset(&r_svbsp, 0, sizeof (r_svbsp));
4117
4118         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4119         r_texture_numcubemaps = 0;
4120
4121         r_refdef.fogmasktable_density = 0;
4122
4123 #ifdef __ANDROID__
4124         // For Steelstorm Android
4125         // FIXME CACHE the program and reload
4126         // FIXME see possible combinations for SS:BR android
4127         Con_DPrintf("Compiling most used shaders for SS:BR android... START\n");
4128         R_SetupShader_SetPermutationGLSL(0, 12);
4129         R_SetupShader_SetPermutationGLSL(0, 13);
4130         R_SetupShader_SetPermutationGLSL(0, 8388621);
4131         R_SetupShader_SetPermutationGLSL(3, 0);
4132         R_SetupShader_SetPermutationGLSL(3, 2048);
4133         R_SetupShader_SetPermutationGLSL(5, 0);
4134         R_SetupShader_SetPermutationGLSL(5, 2);
4135         R_SetupShader_SetPermutationGLSL(5, 2048);
4136         R_SetupShader_SetPermutationGLSL(5, 8388608);
4137         R_SetupShader_SetPermutationGLSL(11, 1);
4138         R_SetupShader_SetPermutationGLSL(11, 2049);
4139         R_SetupShader_SetPermutationGLSL(11, 8193);
4140         R_SetupShader_SetPermutationGLSL(11, 10241);
4141         Con_DPrintf("Compiling most used shaders for SS:BR android... END\n");
4142 #endif
4143 }
4144
4145 static void gl_main_shutdown(void)
4146 {
4147         R_AnimCache_Free();
4148         R_FrameData_Reset();
4149         R_BufferData_Reset();
4150
4151         R_Main_FreeViewCache();
4152
4153         switch(vid.renderpath)
4154         {
4155         case RENDERPATH_GL11:
4156         case RENDERPATH_GL13:
4157         case RENDERPATH_GL20:
4158         case RENDERPATH_GLES1:
4159         case RENDERPATH_GLES2:
4160 #if defined(GL_SAMPLES_PASSED_ARB) && !defined(USE_GLES2)
4161                 if (r_maxqueries)
4162                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4163 #endif
4164                 break;
4165         case RENDERPATH_D3D9:
4166                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4167                 break;
4168         case RENDERPATH_D3D10:
4169                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4170                 break;
4171         case RENDERPATH_D3D11:
4172                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4173                 break;
4174         case RENDERPATH_SOFT:
4175                 break;
4176         }
4177
4178         r_numqueries = 0;
4179         r_maxqueries = 0;
4180         memset(r_queries, 0, sizeof(r_queries));
4181
4182         r_qwskincache = NULL;
4183         r_qwskincache_size = 0;
4184
4185         // clear out the r_skinframe state
4186         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4187         memset(&r_skinframe, 0, sizeof(r_skinframe));
4188
4189         if (r_svbsp.nodes)
4190                 Mem_Free(r_svbsp.nodes);
4191         memset(&r_svbsp, 0, sizeof (r_svbsp));
4192         R_FreeTexturePool(&r_main_texturepool);
4193         loadingscreentexture = NULL;
4194         r_texture_blanknormalmap = NULL;
4195         r_texture_white = NULL;
4196         r_texture_grey128 = NULL;
4197         r_texture_black = NULL;
4198         r_texture_whitecube = NULL;
4199         r_texture_normalizationcube = NULL;
4200         r_texture_fogattenuation = NULL;
4201         r_texture_fogheighttexture = NULL;
4202         r_texture_gammaramps = NULL;
4203         r_texture_numcubemaps = 0;
4204         //r_texture_fogintensity = NULL;
4205         memset(&r_fb, 0, sizeof(r_fb));
4206         R_GLSL_Restart_f();
4207
4208         r_glsl_permutation = NULL;
4209         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4210         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4211         glslshaderstring = NULL;
4212 #ifdef SUPPORTD3D
4213         r_hlsl_permutation = NULL;
4214         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4215         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4216 #endif
4217         hlslshaderstring = NULL;
4218 }
4219
4220 static void gl_main_newmap(void)
4221 {
4222         // FIXME: move this code to client
4223         char *entities, entname[MAX_QPATH];
4224         if (r_qwskincache)
4225                 Mem_Free(r_qwskincache);
4226         r_qwskincache = NULL;
4227         r_qwskincache_size = 0;
4228         if (cl.worldmodel)
4229         {
4230                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4231                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4232                 {
4233                         CL_ParseEntityLump(entities);
4234                         Mem_Free(entities);
4235                         return;
4236                 }
4237                 if (cl.worldmodel->brush.entities)
4238                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4239         }
4240         R_Main_FreeViewCache();
4241
4242         R_FrameData_Reset();
4243         R_BufferData_Reset();
4244 }
4245
4246 void GL_Main_Init(void)
4247 {
4248         int i;
4249         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4250
4251         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4252         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4253         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4254         if (gamemode == GAME_NEHAHRA)
4255         {
4256                 Cvar_RegisterVariable (&gl_fogenable);
4257                 Cvar_RegisterVariable (&gl_fogdensity);
4258                 Cvar_RegisterVariable (&gl_fogred);
4259                 Cvar_RegisterVariable (&gl_foggreen);
4260                 Cvar_RegisterVariable (&gl_fogblue);
4261                 Cvar_RegisterVariable (&gl_fogstart);
4262                 Cvar_RegisterVariable (&gl_fogend);
4263                 Cvar_RegisterVariable (&gl_skyclip);
4264         }
4265         Cvar_RegisterVariable(&r_motionblur);
4266         Cvar_RegisterVariable(&r_damageblur);
4267         Cvar_RegisterVariable(&r_motionblur_averaging);
4268         Cvar_RegisterVariable(&r_motionblur_randomize);
4269         Cvar_RegisterVariable(&r_motionblur_minblur);
4270         Cvar_RegisterVariable(&r_motionblur_maxblur);
4271         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4272         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4273         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4274         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4275         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4276         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4277         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4278         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4279         Cvar_RegisterVariable(&r_equalize_entities_by);
4280         Cvar_RegisterVariable(&r_equalize_entities_to);
4281         Cvar_RegisterVariable(&r_depthfirst);
4282         Cvar_RegisterVariable(&r_useinfinitefarclip);
4283         Cvar_RegisterVariable(&r_farclip_base);
4284         Cvar_RegisterVariable(&r_farclip_world);
4285         Cvar_RegisterVariable(&r_nearclip);
4286         Cvar_RegisterVariable(&r_deformvertexes);
4287         Cvar_RegisterVariable(&r_transparent);
4288         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4289         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4290         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4291         Cvar_RegisterVariable(&r_showoverdraw);
4292         Cvar_RegisterVariable(&r_showbboxes);
4293         Cvar_RegisterVariable(&r_showsurfaces);
4294         Cvar_RegisterVariable(&r_showtris);
4295         Cvar_RegisterVariable(&r_shownormals);
4296         Cvar_RegisterVariable(&r_showlighting);
4297         Cvar_RegisterVariable(&r_showshadowvolumes);
4298         Cvar_RegisterVariable(&r_showcollisionbrushes);
4299         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4300         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4301         Cvar_RegisterVariable(&r_showdisabledepthtest);
4302         Cvar_RegisterVariable(&r_drawportals);
4303         Cvar_RegisterVariable(&r_drawentities);
4304         Cvar_RegisterVariable(&r_draw2d);
4305         Cvar_RegisterVariable(&r_drawworld);
4306         Cvar_RegisterVariable(&r_cullentities_trace);
4307         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4308         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4309         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4310         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4311         Cvar_RegisterVariable(&r_sortentities);
4312         Cvar_RegisterVariable(&r_drawviewmodel);
4313         Cvar_RegisterVariable(&r_drawexteriormodel);
4314         Cvar_RegisterVariable(&r_speeds);
4315         Cvar_RegisterVariable(&r_fullbrights);
4316         Cvar_RegisterVariable(&r_wateralpha);
4317         Cvar_RegisterVariable(&r_dynamic);
4318         Cvar_RegisterVariable(&r_fakelight);
4319         Cvar_RegisterVariable(&r_fakelight_intensity);
4320         Cvar_RegisterVariable(&r_fullbright);
4321         Cvar_RegisterVariable(&r_shadows);
4322         Cvar_RegisterVariable(&r_shadows_darken);
4323         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4324         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4325         Cvar_RegisterVariable(&r_shadows_throwdistance);
4326         Cvar_RegisterVariable(&r_shadows_throwdirection);
4327         Cvar_RegisterVariable(&r_shadows_focus);
4328         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4329         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4330         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4331         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4332         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4333         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4334         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4335         Cvar_RegisterVariable(&r_fog_exp2);
4336         Cvar_RegisterVariable(&r_fog_clear);
4337         Cvar_RegisterVariable(&r_drawfog);
4338         Cvar_RegisterVariable(&r_transparentdepthmasking);
4339         Cvar_RegisterVariable(&r_transparent_sortmindist);
4340         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4341         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4342         Cvar_RegisterVariable(&r_texture_dds_load);
4343         Cvar_RegisterVariable(&r_texture_dds_save);
4344         Cvar_RegisterVariable(&r_textureunits);
4345         Cvar_RegisterVariable(&gl_combine);
4346         Cvar_RegisterVariable(&r_usedepthtextures);
4347         Cvar_RegisterVariable(&r_viewfbo);
4348         Cvar_RegisterVariable(&r_viewscale);
4349         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4350         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4351         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4352         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4353         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4354         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4355         Cvar_RegisterVariable(&r_glsl);
4356         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4357         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4358         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4359         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4360         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4361         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4362         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4363         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4364         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4365         Cvar_RegisterVariable(&r_glsl_postprocess);
4366         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4367         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4368         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4369         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4370         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4371         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4372         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4373         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4374         Cvar_RegisterVariable(&r_celshading);
4375         Cvar_RegisterVariable(&r_celoutlines);
4376
4377         Cvar_RegisterVariable(&r_water);
4378         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4379         Cvar_RegisterVariable(&r_water_clippingplanebias);
4380         Cvar_RegisterVariable(&r_water_refractdistort);
4381         Cvar_RegisterVariable(&r_water_reflectdistort);
4382         Cvar_RegisterVariable(&r_water_scissormode);
4383         Cvar_RegisterVariable(&r_water_lowquality);
4384         Cvar_RegisterVariable(&r_water_hideplayer);
4385         Cvar_RegisterVariable(&r_water_fbo);
4386
4387         Cvar_RegisterVariable(&r_lerpsprites);
4388         Cvar_RegisterVariable(&r_lerpmodels);
4389         Cvar_RegisterVariable(&r_lerplightstyles);
4390         Cvar_RegisterVariable(&r_waterscroll);
4391         Cvar_RegisterVariable(&r_bloom);
4392         Cvar_RegisterVariable(&r_bloom_colorscale);
4393         Cvar_RegisterVariable(&r_bloom_brighten);
4394         Cvar_RegisterVariable(&r_bloom_blur);
4395         Cvar_RegisterVariable(&r_bloom_resolution);
4396         Cvar_RegisterVariable(&r_bloom_colorexponent);
4397         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4398         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4399         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4400         Cvar_RegisterVariable(&r_hdr_glowintensity);
4401         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4402         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4403         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4404         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4405         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4406         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4407         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4408         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4409         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4410         Cvar_RegisterVariable(&developer_texturelogging);
4411         Cvar_RegisterVariable(&gl_lightmaps);
4412         Cvar_RegisterVariable(&r_test);
4413         Cvar_RegisterVariable(&r_batch_multidraw);
4414         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4415         Cvar_RegisterVariable(&r_batch_debugdynamicvertexpath);
4416         Cvar_RegisterVariable(&r_glsl_skeletal);
4417         Cvar_RegisterVariable(&r_glsl_saturation);
4418         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4419         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4420         Cvar_RegisterVariable(&r_framedatasize);
4421         for (i = 0;i < R_BUFFERDATA_COUNT;i++)
4422                 Cvar_RegisterVariable(&r_buffermegs[i]);
4423         Cvar_RegisterVariable(&r_batch_dynamicbuffer);
4424         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4425                 Cvar_SetValue("r_fullbrights", 0);
4426 #ifdef DP_MOBILETOUCH
4427         // GLES devices have terrible depth precision in general, so...
4428         Cvar_SetValueQuick(&r_nearclip, 4);
4429         Cvar_SetValueQuick(&r_farclip_base, 4096);
4430         Cvar_SetValueQuick(&r_farclip_world, 0);
4431         Cvar_SetValueQuick(&r_useinfinitefarclip, 0);
4432 #endif
4433         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4434 }
4435
4436 void Render_Init(void)
4437 {
4438         gl_backend_init();
4439         R_Textures_Init();
4440         GL_Main_Init();
4441         Font_Init();
4442         GL_Draw_Init();
4443         R_Shadow_Init();
4444         R_Sky_Init();
4445         GL_Surf_Init();
4446         Sbar_Init();
4447         R_Particles_Init();
4448         R_Explosion_Init();
4449         R_LightningBeams_Init();
4450         Mod_RenderInit();
4451 }
4452
4453 /*
4454 ===============
4455 GL_Init
4456 ===============
4457 */
4458 #ifndef USE_GLES2
4459 extern char *ENGINE_EXTENSIONS;
4460 void GL_Init (void)
4461 {
4462         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4463         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4464         gl_version = (const char *)qglGetString(GL_VERSION);
4465         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4466
4467         if (!gl_extensions)
4468                 gl_extensions = "";
4469         if (!gl_platformextensions)
4470                 gl_platformextensions = "";
4471
4472         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4473         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4474         Con_Printf("GL_VERSION: %s\n", gl_version);
4475         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4476         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4477
4478         VID_CheckExtensions();
4479
4480         // LordHavoc: report supported extensions
4481 #ifdef CONFIG_MENU
4482         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4483 #else
4484         Con_DPrintf("\nQuakeC extensions for server and client: %s\n", vm_sv_extensions );
4485 #endif
4486
4487         // clear to black (loading plaque will be seen over this)
4488         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4489 }
4490 #endif
4491
4492 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4493 {
4494         int i;
4495         mplane_t *p;
4496         if (r_trippy.integer)
4497                 return false;
4498         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4499         {
4500                 p = r_refdef.view.frustum + i;
4501                 switch(p->signbits)
4502                 {
4503                 default:
4504                 case 0:
4505                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4506                                 return true;
4507                         break;
4508                 case 1:
4509                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4510                                 return true;
4511                         break;
4512                 case 2:
4513                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4514                                 return true;
4515                         break;
4516                 case 3:
4517                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4518                                 return true;
4519                         break;
4520                 case 4:
4521                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4522                                 return true;
4523                         break;
4524                 case 5:
4525                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4526                                 return true;
4527                         break;
4528                 case 6:
4529                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4530                                 return true;
4531                         break;
4532                 case 7:
4533                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4534                                 return true;
4535                         break;
4536                 }
4537         }
4538         return false;
4539 }
4540
4541 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4542 {
4543         int i;
4544         const mplane_t *p;
4545         if (r_trippy.integer)
4546                 return false;
4547         for (i = 0;i < numplanes;i++)
4548         {
4549                 p = planes + i;
4550                 switch(p->signbits)
4551                 {
4552                 default:
4553                 case 0:
4554                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4555                                 return true;
4556                         break;
4557                 case 1:
4558                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4559                                 return true;
4560                         break;
4561                 case 2:
4562                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4563                                 return true;
4564                         break;
4565                 case 3:
4566                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4567                                 return true;
4568                         break;
4569                 case 4:
4570                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4571                                 return true;
4572                         break;
4573                 case 5:
4574                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4575                                 return true;
4576                         break;
4577                 case 6:
4578                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4579                                 return true;
4580                         break;
4581                 case 7:
4582                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4583                                 return true;
4584                         break;
4585                 }
4586         }
4587         return false;
4588 }
4589
4590 //==================================================================================
4591
4592 // LordHavoc: this stores temporary data used within the same frame
4593
4594 typedef struct r_framedata_mem_s
4595 {
4596         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4597         size_t size; // how much usable space
4598         size_t current; // how much space in use
4599         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4600         size_t wantedsize; // how much space was allocated
4601         unsigned char *data; // start of real data (16byte aligned)
4602 }
4603 r_framedata_mem_t;
4604
4605 static r_framedata_mem_t *r_framedata_mem;
4606
4607 void R_FrameData_Reset(void)
4608 {
4609         while (r_framedata_mem)
4610         {
4611                 r_framedata_mem_t *next = r_framedata_mem->purge;
4612                 Mem_Free(r_framedata_mem);
4613                 r_framedata_mem = next;
4614         }
4615 }
4616
4617 static void R_FrameData_Resize(qboolean mustgrow)
4618 {
4619         size_t wantedsize;
4620         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4621         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4622         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize || mustgrow)
4623         {
4624                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4625                 newmem->wantedsize = wantedsize;
4626                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4627                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4628                 newmem->current = 0;
4629                 newmem->mark = 0;
4630                 newmem->purge = r_framedata_mem;
4631                 r_framedata_mem = newmem;
4632         }
4633 }
4634
4635 void R_FrameData_NewFrame(void)
4636 {
4637         R_FrameData_Resize(false);
4638         if (!r_framedata_mem)
4639                 return;
4640         // if we ran out of space on the last frame, free the old memory now
4641         while (r_framedata_mem->purge)
4642         {
4643                 // repeatedly remove the second item in the list, leaving only head
4644                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4645                 Mem_Free(r_framedata_mem->purge);
4646                 r_framedata_mem->purge = next;
4647         }
4648         // reset the current mem pointer
4649         r_framedata_mem->current = 0;
4650         r_framedata_mem->mark = 0;
4651 }
4652
4653 void *R_FrameData_Alloc(size_t size)
4654 {
4655         void *data;
4656         float newvalue;
4657
4658         // align to 16 byte boundary - the data pointer is already aligned, so we
4659         // only need to ensure the size of every allocation is also aligned
4660         size = (size + 15) & ~15;
4661
4662         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4663         {
4664                 // emergency - we ran out of space, allocate more memory
4665                 newvalue = bound(0.25f, r_framedatasize.value * 2.0f, 256.0f);
4666                 // this might not be a growing it, but we'll allocate another buffer every time
4667                 Cvar_SetValueQuick(&r_framedatasize, newvalue);
4668                 R_FrameData_Resize(true);
4669         }
4670
4671         data = r_framedata_mem->data + r_framedata_mem->current;
4672         r_framedata_mem->current += size;
4673
4674         // count the usage for stats
4675         r_refdef.stats[r_stat_framedatacurrent] = max(r_refdef.stats[r_stat_framedatacurrent], (int)r_framedata_mem->current);
4676         r_refdef.stats[r_stat_framedatasize] = max(r_refdef.stats[r_stat_framedatasize], (int)r_framedata_mem->size);
4677
4678         return (void *)data;
4679 }
4680
4681 void *R_FrameData_Store(size_t size, void *data)
4682 {
4683         void *d = R_FrameData_Alloc(size);
4684         if (d && data)
4685                 memcpy(d, data, size);
4686         return d;
4687 }
4688
4689 void R_FrameData_SetMark(void)
4690 {
4691         if (!r_framedata_mem)
4692                 return;
4693         r_framedata_mem->mark = r_framedata_mem->current;
4694 }
4695
4696 void R_FrameData_ReturnToMark(void)
4697 {
4698         if (!r_framedata_mem)
4699                 return;
4700         r_framedata_mem->current = r_framedata_mem->mark;
4701 }
4702
4703 //==================================================================================
4704
4705 // avoid reusing the same buffer objects on consecutive frames
4706 #define R_BUFFERDATA_CYCLE 3
4707
4708 typedef struct r_bufferdata_buffer_s
4709 {
4710         struct r_bufferdata_buffer_s *purge; // older buffer to free on next frame
4711         size_t size; // how much usable space
4712         size_t current; // how much space in use
4713         r_meshbuffer_t *buffer; // the buffer itself
4714 }
4715 r_bufferdata_buffer_t;
4716
4717 static int r_bufferdata_cycle = 0; // incremented and wrapped each frame
4718 static r_bufferdata_buffer_t *r_bufferdata_buffer[R_BUFFERDATA_CYCLE][R_BUFFERDATA_COUNT];
4719
4720 /// frees all dynamic buffers
4721 void R_BufferData_Reset(void)
4722 {
4723         int cycle, type;
4724         r_bufferdata_buffer_t **p, *mem;
4725         for (cycle = 0;cycle < R_BUFFERDATA_CYCLE;cycle++)
4726         {
4727                 for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4728                 {
4729                         // free all buffers
4730                         p = &r_bufferdata_buffer[cycle][type];
4731                         while (*p)
4732                         {
4733                                 mem = *p;
4734                                 *p = (*p)->purge;
4735                                 if (mem->buffer)
4736                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4737                                 Mem_Free(mem);
4738                         }
4739                 }
4740         }
4741 }
4742
4743 // resize buffer as needed (this actually makes a new one, the old one will be recycled next frame)
4744 static void R_BufferData_Resize(r_bufferdata_type_t type, qboolean mustgrow, size_t minsize)
4745 {
4746         r_bufferdata_buffer_t *mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4747         size_t size;
4748         float newvalue = r_buffermegs[type].value;
4749
4750         // increase the cvar if we have to (but only if we already have a mem)
4751         if (mustgrow && mem)
4752                 newvalue *= 2.0f;
4753         newvalue = bound(0.25f, newvalue, 256.0f);
4754         while (newvalue * 1024*1024 < minsize)
4755                 newvalue *= 2.0f;
4756
4757         // clamp the cvar to valid range
4758         newvalue = bound(0.25f, newvalue, 256.0f);
4759         if (r_buffermegs[type].value != newvalue)
4760                 Cvar_SetValueQuick(&r_buffermegs[type], newvalue);
4761
4762         // calculate size in bytes
4763         size = (size_t)(newvalue * 1024*1024);
4764         size = bound(131072, size, 256*1024*1024);
4765
4766         // allocate a new buffer if the size is different (purge old one later)
4767         // or if we were told we must grow the buffer
4768         if (!mem || mem->size != size || mustgrow)
4769         {
4770                 mem = (r_bufferdata_buffer_t *)Mem_Alloc(r_main_mempool, sizeof(*mem));
4771                 mem->size = size;
4772                 mem->current = 0;
4773                 if (type == R_BUFFERDATA_VERTEX)
4774                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbuffervertex", false, false, true, false);
4775                 else if (type == R_BUFFERDATA_INDEX16)
4776                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex16", true, false, true, true);
4777                 else if (type == R_BUFFERDATA_INDEX32)
4778                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferindex32", true, false, true, false);
4779                 else if (type == R_BUFFERDATA_UNIFORM)
4780                         mem->buffer = R_Mesh_CreateMeshBuffer(NULL, mem->size, "dynamicbufferuniform", false, true, true, false);
4781                 mem->purge = r_bufferdata_buffer[r_bufferdata_cycle][type];
4782                 r_bufferdata_buffer[r_bufferdata_cycle][type] = mem;
4783         }
4784 }
4785
4786 void R_BufferData_NewFrame(void)
4787 {
4788         int type;
4789         r_bufferdata_buffer_t **p, *mem;
4790         // cycle to the next frame's buffers
4791         r_bufferdata_cycle = (r_bufferdata_cycle + 1) % R_BUFFERDATA_CYCLE;
4792         // if we ran out of space on the last time we used these buffers, free the old memory now
4793         for (type = 0;type < R_BUFFERDATA_COUNT;type++)
4794         {
4795                 if (r_bufferdata_buffer[r_bufferdata_cycle][type])
4796                 {
4797                         R_BufferData_Resize((r_bufferdata_type_t)type, false, 131072);
4798                         // free all but the head buffer, this is how we recycle obsolete
4799                         // buffers after they are no longer in use
4800                         p = &r_bufferdata_buffer[r_bufferdata_cycle][type]->purge;
4801                         while (*p)
4802                         {
4803                                 mem = *p;
4804                                 *p = (*p)->purge;
4805                                 if (mem->buffer)
4806                                         R_Mesh_DestroyMeshBuffer(mem->buffer);
4807                                 Mem_Free(mem);
4808                         }
4809                         // reset the current offset
4810                         r_bufferdata_buffer[r_bufferdata_cycle][type]->current = 0;
4811                 }
4812         }
4813 }
4814
4815 r_meshbuffer_t *R_BufferData_Store(size_t datasize, const void *data, r_bufferdata_type_t type, int *returnbufferoffset)
4816 {
4817         r_bufferdata_buffer_t *mem;
4818         int offset = 0;
4819         int padsize;
4820
4821         *returnbufferoffset = 0;
4822
4823         // align size to a byte boundary appropriate for the buffer type, this
4824         // makes all allocations have aligned start offsets
4825         if (type == R_BUFFERDATA_UNIFORM)
4826                 padsize = (datasize + r_uniformbufferalignment - 1) & ~(r_uniformbufferalignment - 1);
4827         else
4828                 padsize = (datasize + 15) & ~15;
4829
4830         // if we ran out of space in this buffer we must allocate a new one
4831         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)
4832                 R_BufferData_Resize(type, true, padsize);
4833
4834         // if the resize did not give us enough memory, fail
4835         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)
4836                 Sys_Error("R_BufferData_Store: failed to create a new buffer of sufficient size\n");
4837
4838         mem = r_bufferdata_buffer[r_bufferdata_cycle][type];
4839         offset = (int)mem->current;
4840         mem->current += padsize;
4841
4842         // upload the data to the buffer at the chosen offset
4843         if (offset == 0)
4844                 R_Mesh_UpdateMeshBuffer(mem->buffer, NULL, mem->size, false, 0);
4845         R_Mesh_UpdateMeshBuffer(mem->buffer, data, datasize, true, offset);
4846
4847         // count the usage for stats
4848         r_refdef.stats[r_stat_bufferdatacurrent_vertex + type] = max(r_refdef.stats[r_stat_bufferdatacurrent_vertex + type], (int)mem->current);
4849         r_refdef.stats[r_stat_bufferdatasize_vertex + type] = max(r_refdef.stats[r_stat_bufferdatasize_vertex + type], (int)mem->size);
4850
4851         // return the buffer offset
4852         *returnbufferoffset = offset;
4853
4854         return mem->buffer;
4855 }
4856
4857 //==================================================================================
4858
4859 // LordHavoc: animcache originally written by Echon, rewritten since then
4860
4861 /**
4862  * Animation cache prevents re-generating mesh data for an animated model
4863  * multiple times in one frame for lighting, shadowing, reflections, etc.
4864  */
4865
4866 void R_AnimCache_Free(void)
4867 {
4868 }
4869
4870 void R_AnimCache_ClearCache(void)
4871 {
4872         int i;
4873         entity_render_t *ent;
4874
4875         for (i = 0;i < r_refdef.scene.numentities;i++)
4876         {
4877                 ent = r_refdef.scene.entities[i];
4878                 ent->animcache_vertex3f = NULL;
4879                 ent->animcache_vertex3f_vertexbuffer = NULL;
4880                 ent->animcache_vertex3f_bufferoffset = 0;
4881                 ent->animcache_normal3f = NULL;
4882                 ent->animcache_normal3f_vertexbuffer = NULL;
4883                 ent->animcache_normal3f_bufferoffset = 0;
4884                 ent->animcache_svector3f = NULL;
4885                 ent->animcache_svector3f_vertexbuffer = NULL;
4886                 ent->animcache_svector3f_bufferoffset = 0;
4887                 ent->animcache_tvector3f = NULL;
4888                 ent->animcache_tvector3f_vertexbuffer = NULL;
4889                 ent->animcache_tvector3f_bufferoffset = 0;
4890                 ent->animcache_vertexmesh = NULL;
4891                 ent->animcache_vertexmesh_vertexbuffer = NULL;
4892                 ent->animcache_vertexmesh_bufferoffset = 0;
4893                 ent->animcache_skeletaltransform3x4 = NULL;
4894                 ent->animcache_skeletaltransform3x4buffer = NULL;
4895                 ent->animcache_skeletaltransform3x4offset = 0;
4896                 ent->animcache_skeletaltransform3x4size = 0;
4897         }
4898 }
4899
4900 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4901 {
4902         int i;
4903
4904         // check if we need the meshbuffers
4905         if (!vid.useinterleavedarrays)
4906                 return;
4907
4908         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4909                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4910         // TODO: upload vertexbuffer?
4911         if (ent->animcache_vertexmesh)
4912         {
4913                 r_refdef.stats[r_stat_animcache_vertexmesh_count] += 1;
4914                 r_refdef.stats[r_stat_animcache_vertexmesh_vertices] += numvertices;
4915                 r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices] = max(r_refdef.stats[r_stat_animcache_vertexmesh_maxvertices], numvertices);
4916                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.data_vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4917                 for (i = 0;i < numvertices;i++)
4918                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4919                 if (ent->animcache_svector3f)
4920                         for (i = 0;i < numvertices;i++)
4921                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4922                 if (ent->animcache_tvector3f)
4923                         for (i = 0;i < numvertices;i++)
4924                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4925                 if (ent->animcache_normal3f)
4926                         for (i = 0;i < numvertices;i++)
4927                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4928         }
4929 }
4930
4931 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4932 {
4933         dp_model_t *model = ent->model;
4934         int numvertices;
4935
4936         // see if this ent is worth caching
4937         if (!model || !model->Draw || !model->AnimateVertices)
4938                 return false;
4939         // nothing to cache if it contains no animations and has no skeleton
4940         if (!model->surfmesh.isanimated && !(model->num_bones && ent->skeleton && ent->skeleton->relativetransforms))
4941                 return false;
4942         // see if it is already cached for gpuskeletal
4943         if (ent->animcache_skeletaltransform3x4)
4944                 return false;
4945         // see if it is already cached as a mesh
4946         if (ent->animcache_vertex3f)
4947         {
4948                 // check if we need to add normals or tangents
4949                 if (ent->animcache_normal3f)
4950                         wantnormals = false;
4951                 if (ent->animcache_svector3f)
4952                         wanttangents = false;
4953                 if (!wantnormals && !wanttangents)
4954                         return false;
4955         }
4956
4957         // check which kind of cache we need to generate
4958         if (r_gpuskeletal && model->num_bones > 0 && model->surfmesh.data_skeletalindex4ub)
4959         {
4960                 // cache the skeleton so the vertex shader can use it
4961                 r_refdef.stats[r_stat_animcache_skeletal_count] += 1;
4962                 r_refdef.stats[r_stat_animcache_skeletal_bones] += model->num_bones;
4963                 r_refdef.stats[r_stat_animcache_skeletal_maxbones] = max(r_refdef.stats[r_stat_animcache_skeletal_maxbones], model->num_bones);
4964                 ent->animcache_skeletaltransform3x4 = (float *)R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4965                 Mod_Skeletal_BuildTransforms(model, ent->frameblend, ent->skeleton, NULL, ent->animcache_skeletaltransform3x4); 
4966                 // note: this can fail if the buffer is at the grow limit
4967                 ent->animcache_skeletaltransform3x4size = sizeof(float[3][4]) * model->num_bones;
4968                 ent->animcache_skeletaltransform3x4buffer = R_BufferData_Store(ent->animcache_skeletaltransform3x4size, ent->animcache_skeletaltransform3x4, R_BUFFERDATA_UNIFORM, &ent->animcache_skeletaltransform3x4offset);
4969         }
4970         else if (ent->animcache_vertex3f)
4971         {
4972                 // mesh was already cached but we may need to add normals/tangents
4973                 // (this only happens with multiple views, reflections, cameras, etc)
4974                 if (wantnormals || wanttangents)
4975                 {
4976                         numvertices = model->surfmesh.num_vertices;
4977                         if (wantnormals)
4978                                 ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4979                         if (wanttangents)
4980                         {
4981                                 ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4982                                 ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4983                         }
4984                         model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4985                         R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4986                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
4987                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
4988                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
4989                 }
4990         }
4991         else
4992         {
4993                 // generate mesh cache
4994                 numvertices = model->surfmesh.num_vertices;
4995                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4996                 if (wantnormals)
4997                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4998                 if (wanttangents)
4999                 {
5000                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5001                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
5002                 }
5003                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
5004                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
5005                 if (wantnormals || wanttangents)
5006                 {
5007                         r_refdef.stats[r_stat_animcache_shade_count] += 1;
5008                         r_refdef.stats[r_stat_animcache_shade_vertices] += numvertices;
5009                         r_refdef.stats[r_stat_animcache_shade_maxvertices] = max(r_refdef.stats[r_stat_animcache_shade_maxvertices], numvertices);
5010                 }
5011                 r_refdef.stats[r_stat_animcache_shape_count] += 1;
5012                 r_refdef.stats[r_stat_animcache_shape_vertices] += numvertices;
5013                 r_refdef.stats[r_stat_animcache_shape_maxvertices] = max(r_refdef.stats[r_stat_animcache_shape_maxvertices], numvertices);
5014         }
5015         return true;
5016 }
5017
5018 void R_AnimCache_CacheVisibleEntities(void)
5019 {
5020         int i;
5021         qboolean wantnormals = true;
5022         qboolean wanttangents = !r_showsurfaces.integer;
5023
5024         switch(vid.renderpath)
5025         {
5026         case RENDERPATH_GL20:
5027         case RENDERPATH_D3D9:
5028         case RENDERPATH_D3D10:
5029         case RENDERPATH_D3D11:
5030         case RENDERPATH_GLES2:
5031                 break;
5032         case RENDERPATH_GL11:
5033         case RENDERPATH_GL13:
5034         case RENDERPATH_GLES1:
5035                 wanttangents = false;
5036                 break;
5037         case RENDERPATH_SOFT:
5038                 break;
5039         }
5040
5041         if (r_shownormals.integer)
5042                 wanttangents = wantnormals = true;
5043
5044         // TODO: thread this
5045         // NOTE: R_PrepareRTLights() also caches entities
5046
5047         for (i = 0;i < r_refdef.scene.numentities;i++)
5048                 if (r_refdef.viewcache.entityvisible[i])
5049                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
5050 }
5051
5052 //==================================================================================
5053
5054 extern cvar_t r_overheadsprites_pushback;
5055
5056 static void R_View_UpdateEntityLighting (void)
5057 {
5058         int i;
5059         entity_render_t *ent;
5060         vec3_t tempdiffusenormal, avg;
5061         vec_t f, fa, fd, fdd;
5062         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
5063
5064         for (i = 0;i < r_refdef.scene.numentities;i++)
5065         {
5066                 ent = r_refdef.scene.entities[i];
5067
5068                 // skip unseen models
5069                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
5070                         continue;
5071
5072                 // skip bsp models
5073                 if (ent->model && ent->model == cl.worldmodel)
5074                 {
5075                         // TODO: use modellight for r_ambient settings on world?
5076                         VectorSet(ent->modellight_ambient, 0, 0, 0);
5077                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
5078                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
5079                         continue;
5080                 }
5081                 
5082                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
5083                 {
5084                         // aleady updated by CSQC
5085                         // TODO: force modellight on BSP models in this case?
5086                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
5087                 }
5088                 else
5089                 {
5090                         // fetch the lighting from the worldmodel data
5091                         VectorClear(ent->modellight_ambient);
5092                         VectorClear(ent->modellight_diffuse);
5093                         VectorClear(tempdiffusenormal);
5094                         if (ent->flags & RENDER_LIGHT)
5095                         {
5096                                 vec3_t org;
5097                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
5098
5099                                 // complete lightning for lit sprites
5100                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
5101                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
5102                                 {
5103                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
5104                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
5105                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5106                                 }
5107                                 else
5108                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
5109
5110                                 if(ent->flags & RENDER_EQUALIZE)
5111                                 {
5112                                         // first fix up ambient lighting...
5113                                         if(r_equalize_entities_minambient.value > 0)
5114                                         {
5115                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5116                                                 if(fd > 0)
5117                                                 {
5118                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
5119                                                         if(fa < r_equalize_entities_minambient.value * fd)
5120                                                         {
5121                                                                 // solve:
5122                                                                 //   fa'/fd' = minambient
5123                                                                 //   fa'+0.25*fd' = fa+0.25*fd
5124                                                                 //   ...
5125                                                                 //   fa' = fd' * minambient
5126                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
5127                                                                 //   ...
5128                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
5129                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
5130                                                                 //   ...
5131                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
5132                                                                 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
5133                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
5134                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
5135                                                         }
5136                                                 }
5137                                         }
5138
5139                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
5140                                         {
5141                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
5142                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
5143                                                 f = fa + 0.25 * fd;
5144                                                 if(f > 0)
5145                                                 {
5146                                                         // adjust brightness and saturation to target
5147                                                         avg[0] = avg[1] = avg[2] = fa / f;
5148                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
5149                                                         avg[0] = avg[1] = avg[2] = fd / f;
5150                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
5151                                                 }
5152                                         }
5153                                 }
5154                         }
5155                         else // highly rare
5156                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
5157                 }
5158
5159                 // move the light direction into modelspace coordinates for lighting code
5160                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
5161                 if(VectorLength2(ent->modellight_lightdir) == 0)
5162                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
5163                 VectorNormalize(ent->modellight_lightdir);
5164         }
5165 }
5166
5167 #define MAX_LINEOFSIGHTTRACES 64
5168
5169 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
5170 {
5171         int i;
5172         vec3_t boxmins, boxmaxs;
5173         vec3_t start;
5174         vec3_t end;
5175         dp_model_t *model = r_refdef.scene.worldmodel;
5176
5177         if (!model || !model->brush.TraceLineOfSight)
5178                 return true;
5179
5180         // expand the box a little
5181         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
5182         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
5183         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
5184         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
5185         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5186         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5187
5188         // return true if eye is inside enlarged box
5189         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5190                 return true;
5191
5192         // try center
5193         VectorCopy(eye, start);
5194         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5195         if (model->brush.TraceLineOfSight(model, start, end))
5196                 return true;
5197
5198         // try various random positions
5199         for (i = 0;i < numsamples;i++)
5200         {
5201                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5202                 if (model->brush.TraceLineOfSight(model, start, end))
5203                         return true;
5204         }
5205
5206         return false;
5207 }
5208
5209
5210 static void R_View_UpdateEntityVisible (void)
5211 {
5212         int i;
5213         int renderimask;
5214         int samples;
5215         entity_render_t *ent;
5216
5217         if (r_refdef.envmap || r_fb.water.hideplayer)
5218                 renderimask = RENDER_EXTERIORMODEL | RENDER_VIEWMODEL;
5219         else if (chase_active.integer || r_fb.water.renderingscene)
5220                 renderimask = RENDER_VIEWMODEL;
5221         else
5222                 renderimask = RENDER_EXTERIORMODEL;
5223         if (!r_drawviewmodel.integer)
5224                 renderimask |= RENDER_VIEWMODEL;
5225         if (!r_drawexteriormodel.integer)
5226                 renderimask |= RENDER_EXTERIORMODEL;
5227         memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5228         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5229         {
5230                 // worldmodel can check visibility
5231                 for (i = 0;i < r_refdef.scene.numentities;i++)
5232                 {
5233                         ent = r_refdef.scene.entities[i];
5234                         if (!(ent->flags & renderimask))
5235                         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)))
5236                         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))
5237                                 r_refdef.viewcache.entityvisible[i] = true;
5238                 }
5239         }
5240         else
5241         {
5242                 // no worldmodel or it can't check visibility
5243                 for (i = 0;i < r_refdef.scene.numentities;i++)
5244                 {
5245                         ent = r_refdef.scene.entities[i];
5246                         if (!(ent->flags & renderimask))
5247                         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)))
5248                                 r_refdef.viewcache.entityvisible[i] = true;
5249                 }
5250         }
5251         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5252                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5253         {
5254                 for (i = 0;i < r_refdef.scene.numentities;i++)
5255                 {
5256                         if (!r_refdef.viewcache.entityvisible[i])
5257                                 continue;
5258                         ent = r_refdef.scene.entities[i];
5259                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5260                         {
5261                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5262                                 if (samples < 0)
5263                                         continue; // temp entities do pvs only
5264                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5265                                         ent->last_trace_visibility = realtime;
5266                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5267                                         r_refdef.viewcache.entityvisible[i] = 0;
5268                         }
5269                 }
5270         }
5271 }
5272
5273 /// only used if skyrendermasked, and normally returns false
5274 static int R_DrawBrushModelsSky (void)
5275 {
5276         int i, sky;
5277         entity_render_t *ent;
5278
5279         sky = false;
5280         for (i = 0;i < r_refdef.scene.numentities;i++)
5281         {
5282                 if (!r_refdef.viewcache.entityvisible[i])
5283                         continue;
5284                 ent = r_refdef.scene.entities[i];
5285                 if (!ent->model || !ent->model->DrawSky)
5286                         continue;
5287                 ent->model->DrawSky(ent);
5288                 sky = true;
5289         }
5290         return sky;
5291 }
5292
5293 static void R_DrawNoModel(entity_render_t *ent);
5294 static void R_DrawModels(void)
5295 {
5296         int i;
5297         entity_render_t *ent;
5298
5299         for (i = 0;i < r_refdef.scene.numentities;i++)
5300         {
5301                 if (!r_refdef.viewcache.entityvisible[i])
5302                         continue;
5303                 ent = r_refdef.scene.entities[i];
5304                 r_refdef.stats[r_stat_entities]++;
5305                 /*
5306                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5307                 {
5308                         vec3_t f, l, u, o;
5309                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5310                         Con_Printf("R_DrawModels\n");
5311                         Con_Printf("model %s O %f %f %f F %f %f %f L %f %f %f U %f %f %f\n", ent->model->name, o[0], o[1], o[2], f[0], f[1], f[2], l[0], l[1], l[2], u[0], u[1], u[2]);
5312                         Con_Printf("group: %i %f %i %f %i %f %i %f\n", ent->framegroupblend[0].frame, ent->framegroupblend[0].lerp, ent->framegroupblend[1].frame, ent->framegroupblend[1].lerp, ent->framegroupblend[2].frame, ent->framegroupblend[2].lerp, ent->framegroupblend[3].frame, ent->framegroupblend[3].lerp);
5313                         Con_Printf("blend: %i %f %i %f %i %f %i %f %i %f %i %f %i %f %i %f\n", ent->frameblend[0].subframe, ent->frameblend[0].lerp, ent->frameblend[1].subframe, ent->frameblend[1].lerp, ent->frameblend[2].subframe, ent->frameblend[2].lerp, ent->frameblend[3].subframe, ent->frameblend[3].lerp, ent->frameblend[4].subframe, ent->frameblend[4].lerp, ent->frameblend[5].subframe, ent->frameblend[5].lerp, ent->frameblend[6].subframe, ent->frameblend[6].lerp, ent->frameblend[7].subframe, ent->frameblend[7].lerp);
5314                 }
5315                 */
5316                 if (ent->model && ent->model->Draw != NULL)
5317                         ent->model->Draw(ent);
5318                 else
5319                         R_DrawNoModel(ent);
5320         }
5321 }
5322
5323 static void R_DrawModelsDepth(void)
5324 {
5325         int i;
5326         entity_render_t *ent;
5327
5328         for (i = 0;i < r_refdef.scene.numentities;i++)
5329         {
5330                 if (!r_refdef.viewcache.entityvisible[i])
5331                         continue;
5332                 ent = r_refdef.scene.entities[i];
5333                 if (ent->model && ent->model->DrawDepth != NULL)
5334                         ent->model->DrawDepth(ent);
5335         }
5336 }
5337
5338 static void R_DrawModelsDebug(void)
5339 {
5340         int i;
5341         entity_render_t *ent;
5342
5343         for (i = 0;i < r_refdef.scene.numentities;i++)
5344         {
5345                 if (!r_refdef.viewcache.entityvisible[i])
5346                         continue;
5347                 ent = r_refdef.scene.entities[i];
5348                 if (ent->model && ent->model->DrawDebug != NULL)
5349                         ent->model->DrawDebug(ent);
5350         }
5351 }
5352
5353 static void R_DrawModelsAddWaterPlanes(void)
5354 {
5355         int i;
5356         entity_render_t *ent;
5357
5358         for (i = 0;i < r_refdef.scene.numentities;i++)
5359         {
5360                 if (!r_refdef.viewcache.entityvisible[i])
5361                         continue;
5362                 ent = r_refdef.scene.entities[i];
5363                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5364                         ent->model->DrawAddWaterPlanes(ent);
5365         }
5366 }
5367
5368 static float irisvecs[7][3] = {{0, 0, 0}, {-1, 0, 0}, {1, 0, 0}, {0, -1, 0}, {0, 1, 0}, {0, 0, -1}, {0, 0, 1}};
5369
5370 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5371 {
5372         if (r_hdr_irisadaptation.integer)
5373         {
5374                 vec3_t p;
5375                 vec3_t ambient;
5376                 vec3_t diffuse;
5377                 vec3_t diffusenormal;
5378                 vec3_t forward;
5379                 vec_t brightness = 0.0f;
5380                 vec_t goal;
5381                 vec_t current;
5382                 vec_t d;
5383                 int c;
5384                 VectorCopy(r_refdef.view.forward, forward);
5385                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5386                 {
5387                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5388                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5389                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5390                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5391                         d = DotProduct(forward, diffusenormal);
5392                         brightness += VectorLength(ambient);
5393                         if (d > 0)
5394                                 brightness += d * VectorLength(diffuse);
5395                 }
5396                 brightness *= 1.0f / c;
5397                 brightness += 0.00001f; // make sure it's never zero
5398                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5399                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5400                 current = r_hdr_irisadaptation_value.value;
5401                 if (current < goal)
5402                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5403                 else if (current > goal)
5404                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5405                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5406                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5407         }
5408         else if (r_hdr_irisadaptation_value.value != 1.0f)
5409                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5410 }
5411
5412 static void R_View_SetFrustum(const int *scissor)
5413 {
5414         int i;
5415         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5416         vec3_t forward, left, up, origin, v;
5417
5418         if(scissor)
5419         {
5420                 // flipped x coordinates (because x points left here)
5421                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5422                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5423
5424                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5425                 switch(vid.renderpath)
5426                 {
5427                         case RENDERPATH_D3D9:
5428                         case RENDERPATH_D3D10:
5429                         case RENDERPATH_D3D11:
5430                                 // non-flipped y coordinates
5431                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5432                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5433                                 break;
5434                         case RENDERPATH_SOFT:
5435                         case RENDERPATH_GL11:
5436                         case RENDERPATH_GL13:
5437                         case RENDERPATH_GL20:
5438                         case RENDERPATH_GLES1:
5439                         case RENDERPATH_GLES2:
5440                                 // non-flipped y coordinates
5441                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5442                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5443                                 break;
5444                 }
5445         }
5446
5447         // we can't trust r_refdef.view.forward and friends in reflected scenes
5448         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5449
5450 #if 0
5451         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5452         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5453         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5454         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5455         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5456         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5457         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5458         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5459         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5460         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5461         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5462         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5463 #endif
5464
5465 #if 0
5466         zNear = r_refdef.nearclip;
5467         nudge = 1.0 - 1.0 / (1<<23);
5468         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5469         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5470         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5471         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5472         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5473         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5474         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5475         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5476 #endif
5477
5478
5479
5480 #if 0
5481         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5482         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5483         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5484         r_refdef.view.frustum[0].dist = m[15] - m[12];
5485
5486         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5487         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5488         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5489         r_refdef.view.frustum[1].dist = m[15] + m[12];
5490
5491         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5492         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5493         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5494         r_refdef.view.frustum[2].dist = m[15] - m[13];
5495
5496         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5497         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5498         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5499         r_refdef.view.frustum[3].dist = m[15] + m[13];
5500
5501         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5502         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5503         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5504         r_refdef.view.frustum[4].dist = m[15] - m[14];
5505
5506         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5507         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5508         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5509         r_refdef.view.frustum[5].dist = m[15] + m[14];
5510 #endif
5511
5512         if (r_refdef.view.useperspective)
5513         {
5514                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5515                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[0]);
5516                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fny * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[1]);
5517                 VectorMAMAM(1024, forward, fnx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[2]);
5518                 VectorMAMAM(1024, forward, fpx * 1024.0 * r_refdef.view.frustum_x, left, fpy * 1024.0 * r_refdef.view.frustum_y, up, r_refdef.view.frustumcorner[3]);
5519
5520                 // then the normals from the corners relative to origin
5521                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5522                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5523                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5524                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5525
5526                 // in a NORMAL view, forward cross left == up
5527                 // in a REFLECTED view, forward cross left == down
5528                 // so our cross products above need to be adjusted for a left handed coordinate system
5529                 CrossProduct(forward, left, v);
5530                 if(DotProduct(v, up) < 0)
5531                 {
5532                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5533                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5534                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5535                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5536                 }
5537
5538                 // Leaving those out was a mistake, those were in the old code, and they
5539                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5540                 // I couldn't reproduce it after adding those normalizations. --blub
5541                 VectorNormalize(r_refdef.view.frustum[0].normal);
5542                 VectorNormalize(r_refdef.view.frustum[1].normal);
5543                 VectorNormalize(r_refdef.view.frustum[2].normal);
5544                 VectorNormalize(r_refdef.view.frustum[3].normal);
5545
5546                 // make the corners absolute
5547                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5548                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5549                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5550                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5551
5552                 // one more normal
5553                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5554
5555                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5556                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5557                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5558                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5559                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5560         }
5561         else
5562         {
5563                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5564                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5565                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5566                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5567                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5568                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5569                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5570                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5571                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5572                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5573         }
5574         r_refdef.view.numfrustumplanes = 5;
5575
5576         if (r_refdef.view.useclipplane)
5577         {
5578                 r_refdef.view.numfrustumplanes = 6;
5579                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5580         }
5581
5582         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5583                 PlaneClassify(r_refdef.view.frustum + i);
5584
5585         // LordHavoc: note to all quake engine coders, Quake had a special case
5586         // for 90 degrees which assumed a square view (wrong), so I removed it,
5587         // Quake2 has it disabled as well.
5588
5589         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5590         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5591         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5592         //PlaneClassify(&frustum[0]);
5593
5594         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5595         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5596         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5597         //PlaneClassify(&frustum[1]);
5598
5599         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5600         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5601         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5602         //PlaneClassify(&frustum[2]);
5603
5604         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5605         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5606         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5607         //PlaneClassify(&frustum[3]);
5608
5609         // nearclip plane
5610         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5611         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5612         //PlaneClassify(&frustum[4]);
5613 }
5614
5615 static void R_View_UpdateWithScissor(const int *myscissor)
5616 {
5617         R_Main_ResizeViewCache();
5618         R_View_SetFrustum(myscissor);
5619         R_View_WorldVisibility(r_refdef.view.useclipplane);
5620         R_View_UpdateEntityVisible();
5621         R_View_UpdateEntityLighting();
5622 }
5623
5624 static void R_View_Update(void)
5625 {
5626         R_Main_ResizeViewCache();
5627         R_View_SetFrustum(NULL);
5628         R_View_WorldVisibility(r_refdef.view.useclipplane);
5629         R_View_UpdateEntityVisible();
5630         R_View_UpdateEntityLighting();
5631 }
5632
5633 float viewscalefpsadjusted = 1.0f;
5634
5635 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5636 {
5637         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5638         scale = bound(0.03125f, scale, 1.0f);
5639         *outwidth = (int)ceil(width * scale);
5640         *outheight = (int)ceil(height * scale);
5641 }
5642
5643 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5644 {
5645         const float *customclipplane = NULL;
5646         float plane[4];
5647         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5648         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5649         {
5650                 // LordHavoc: couldn't figure out how to make this approach the
5651                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5652                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5653                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5654                         dist = r_refdef.view.clipplane.dist;
5655                 plane[0] = r_refdef.view.clipplane.normal[0];
5656                 plane[1] = r_refdef.view.clipplane.normal[1];
5657                 plane[2] = r_refdef.view.clipplane.normal[2];
5658                 plane[3] = -dist;
5659                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5660         }
5661
5662         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5663         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5664
5665         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5666         if (!r_refdef.view.useperspective)
5667                 R_Viewport_InitOrtho(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, -r_refdef.view.ortho_x, -r_refdef.view.ortho_y, r_refdef.view.ortho_x, r_refdef.view.ortho_y, -r_refdef.farclip, r_refdef.farclip, customclipplane);
5668         else if (vid.stencil && r_useinfinitefarclip.integer)
5669                 R_Viewport_InitPerspectiveInfinite(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, customclipplane);
5670         else
5671                 R_Viewport_InitPerspective(&r_refdef.view.viewport, &r_refdef.view.matrix, r_refdef.view.x, rtheight - scaledheight - r_refdef.view.y, scaledwidth, scaledheight, r_refdef.view.frustum_x, r_refdef.view.frustum_y, r_refdef.nearclip, r_refdef.farclip, customclipplane);
5672         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5673         R_SetViewport(&r_refdef.view.viewport);
5674         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5675         {
5676                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5677                 float screenplane[4];
5678                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5679                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5680                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5681                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5682                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5683         }
5684 }
5685
5686 void R_EntityMatrix(const matrix4x4_t *matrix)
5687 {
5688         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5689         {
5690                 gl_modelmatrixchanged = false;
5691                 gl_modelmatrix = *matrix;
5692                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5693                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5694                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5695                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5696                 CHECKGLERROR
5697                 switch(vid.renderpath)
5698                 {
5699                 case RENDERPATH_D3D9:
5700 #ifdef SUPPORTD3D
5701                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5702                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5703 #endif
5704                         break;
5705                 case RENDERPATH_D3D10:
5706                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5707                         break;
5708                 case RENDERPATH_D3D11:
5709                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5710                         break;
5711                 case RENDERPATH_GL11:
5712                 case RENDERPATH_GL13:
5713                 case RENDERPATH_GLES1:
5714 #ifndef USE_GLES2
5715                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5716 #endif
5717                         break;
5718                 case RENDERPATH_SOFT:
5719                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5720                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5721                         break;
5722                 case RENDERPATH_GL20:
5723                 case RENDERPATH_GLES2:
5724                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5725                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5726                         break;
5727                 }
5728         }
5729 }
5730
5731 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5732 {
5733         r_viewport_t viewport;
5734
5735         CHECKGLERROR
5736
5737         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5738         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);
5739         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5740         R_SetViewport(&viewport);
5741         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5742         GL_Color(1, 1, 1, 1);
5743         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5744         GL_BlendFunc(GL_ONE, GL_ZERO);
5745         GL_ScissorTest(false);
5746         GL_DepthMask(false);
5747         GL_DepthRange(0, 1);
5748         GL_DepthTest(false);
5749         GL_DepthFunc(GL_LEQUAL);
5750         R_EntityMatrix(&identitymatrix);
5751         R_Mesh_ResetTextureState();
5752         GL_PolygonOffset(0, 0);
5753         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5754         switch(vid.renderpath)
5755         {
5756         case RENDERPATH_GL11:
5757         case RENDERPATH_GL13:
5758         case RENDERPATH_GL20:
5759         case RENDERPATH_GLES1:
5760         case RENDERPATH_GLES2:
5761                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5762                 break;
5763         case RENDERPATH_D3D9:
5764         case RENDERPATH_D3D10:
5765         case RENDERPATH_D3D11:
5766         case RENDERPATH_SOFT:
5767                 break;
5768         }
5769         GL_CullFace(GL_NONE);
5770
5771         CHECKGLERROR
5772 }
5773
5774 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5775 {
5776         DrawQ_Finish();
5777
5778         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5779 }
5780
5781 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5782 {
5783         DrawQ_Finish();
5784
5785         R_SetupView(true, fbo, depthtexture, colortexture);
5786         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5787         GL_Color(1, 1, 1, 1);
5788         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5789         GL_BlendFunc(GL_ONE, GL_ZERO);
5790         GL_ScissorTest(true);
5791         GL_DepthMask(true);
5792         GL_DepthRange(0, 1);
5793         GL_DepthTest(true);
5794         GL_DepthFunc(GL_LEQUAL);
5795         R_EntityMatrix(&identitymatrix);
5796         R_Mesh_ResetTextureState();
5797         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5798         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5799         switch(vid.renderpath)
5800         {
5801         case RENDERPATH_GL11:
5802         case RENDERPATH_GL13:
5803         case RENDERPATH_GL20:
5804         case RENDERPATH_GLES1:
5805         case RENDERPATH_GLES2:
5806                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5807                 break;
5808         case RENDERPATH_D3D9:
5809         case RENDERPATH_D3D10:
5810         case RENDERPATH_D3D11:
5811         case RENDERPATH_SOFT:
5812                 break;
5813         }
5814         GL_CullFace(r_refdef.view.cullface_back);
5815 }
5816
5817 /*
5818 ================
5819 R_RenderView_UpdateViewVectors
5820 ================
5821 */
5822 void R_RenderView_UpdateViewVectors(void)
5823 {
5824         // break apart the view matrix into vectors for various purposes
5825         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5826         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5827         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5828         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5829         // make an inverted copy of the view matrix for tracking sprites
5830         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5831 }
5832
5833 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5834 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5835
5836 static void R_Water_StartFrame(void)
5837 {
5838         int i;
5839         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5840         r_waterstate_waterplane_t *p;
5841         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;
5842
5843         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5844                 return;
5845
5846         switch(vid.renderpath)
5847         {
5848         case RENDERPATH_GL20:
5849         case RENDERPATH_D3D9:
5850         case RENDERPATH_D3D10:
5851         case RENDERPATH_D3D11:
5852         case RENDERPATH_SOFT:
5853         case RENDERPATH_GLES2:
5854                 break;
5855         case RENDERPATH_GL11:
5856         case RENDERPATH_GL13:
5857         case RENDERPATH_GLES1:
5858                 return;
5859         }
5860
5861         // set waterwidth and waterheight to the water resolution that will be
5862         // used (often less than the screen resolution for faster rendering)
5863         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5864
5865         // calculate desired texture sizes
5866         // can't use water if the card does not support the texture size
5867         if (!r_water.integer || r_showsurfaces.integer)
5868                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5869         else if (vid.support.arb_texture_non_power_of_two)
5870         {
5871                 texturewidth = waterwidth;
5872                 textureheight = waterheight;
5873                 camerawidth = waterwidth;
5874                 cameraheight = waterheight;
5875         }
5876         else
5877         {
5878                 for (texturewidth   = 1;texturewidth     <  waterwidth ;texturewidth   *= 2);
5879                 for (textureheight  = 1;textureheight    <  waterheight;textureheight  *= 2);
5880                 for (camerawidth    = 1;camerawidth  * 2 <= waterwidth ;camerawidth    *= 2);
5881                 for (cameraheight   = 1;cameraheight * 2 <= waterheight;cameraheight   *= 2);
5882         }
5883
5884         // allocate textures as needed
5885         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))
5886         {
5887                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5888                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5889                 {
5890                         if (p->texture_refraction)
5891                                 R_FreeTexture(p->texture_refraction);
5892                         p->texture_refraction = NULL;
5893                         if (p->fbo_refraction)
5894                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5895                         p->fbo_refraction = 0;
5896                         if (p->texture_reflection)
5897                                 R_FreeTexture(p->texture_reflection);
5898                         p->texture_reflection = NULL;
5899                         if (p->fbo_reflection)
5900                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5901                         p->fbo_reflection = 0;
5902                         if (p->texture_camera)
5903                                 R_FreeTexture(p->texture_camera);
5904                         p->texture_camera = NULL;
5905                         if (p->fbo_camera)
5906                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5907                         p->fbo_camera = 0;
5908                 }
5909                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5910                 r_fb.water.texturewidth = texturewidth;
5911                 r_fb.water.textureheight = textureheight;
5912                 r_fb.water.camerawidth = camerawidth;
5913                 r_fb.water.cameraheight = cameraheight;
5914         }
5915
5916         if (r_fb.water.texturewidth)
5917         {
5918                 int scaledwidth, scaledheight;
5919
5920                 r_fb.water.enabled = true;
5921
5922                 // water resolution is usually reduced
5923                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5924                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5925                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5926
5927                 // set up variables that will be used in shader setup
5928                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5929                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5930                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5931                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5932         }
5933
5934         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5935         r_fb.water.numwaterplanes = 0;
5936 }
5937
5938 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5939 {
5940         int planeindex, bestplaneindex, vertexindex;
5941         vec3_t mins, maxs, normal, center, v, n;
5942         vec_t planescore, bestplanescore;
5943         mplane_t plane;
5944         r_waterstate_waterplane_t *p;
5945         texture_t *t = R_GetCurrentTexture(surface->texture);
5946
5947         rsurface.texture = t;
5948         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5949         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5950         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5951                 return;
5952         // average the vertex normals, find the surface bounds (after deformvertexes)
5953         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5954         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5955         VectorCopy(n, normal);
5956         VectorCopy(v, mins);
5957         VectorCopy(v, maxs);
5958         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5959         {
5960                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5961                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5962                 VectorAdd(normal, n, normal);
5963                 mins[0] = min(mins[0], v[0]);
5964                 mins[1] = min(mins[1], v[1]);
5965                 mins[2] = min(mins[2], v[2]);
5966                 maxs[0] = max(maxs[0], v[0]);
5967                 maxs[1] = max(maxs[1], v[1]);
5968                 maxs[2] = max(maxs[2], v[2]);
5969         }
5970         VectorNormalize(normal);
5971         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5972
5973         VectorCopy(normal, plane.normal);
5974         VectorNormalize(plane.normal);
5975         plane.dist = DotProduct(center, plane.normal);
5976         PlaneClassify(&plane);
5977         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5978         {
5979                 // skip backfaces (except if nocullface is set)
5980 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5981 //                      return;
5982                 VectorNegate(plane.normal, plane.normal);
5983                 plane.dist *= -1;
5984                 PlaneClassify(&plane);
5985         }
5986
5987
5988         // find a matching plane if there is one
5989         bestplaneindex = -1;
5990         bestplanescore = 1048576.0f;
5991         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5992         {
5993                 if(p->camera_entity == t->camera_entity)
5994                 {
5995                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5996                         if (bestplaneindex < 0 || bestplanescore > planescore)
5997                         {
5998                                 bestplaneindex = planeindex;
5999                                 bestplanescore = planescore;
6000                         }
6001                 }
6002         }
6003         planeindex = bestplaneindex;
6004         p = r_fb.water.waterplanes + planeindex;
6005
6006         // if this surface does not fit any known plane rendered this frame, add one
6007         if (planeindex < 0 || bestplanescore > 0.001f)
6008         {
6009                 if (r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
6010                 {
6011                         // store the new plane
6012                         planeindex = r_fb.water.numwaterplanes++;
6013                         p = r_fb.water.waterplanes + planeindex;
6014                         p->plane = plane;
6015                         // clear materialflags and pvs
6016                         p->materialflags = 0;
6017                         p->pvsvalid = false;
6018                         p->camera_entity = t->camera_entity;
6019                         VectorCopy(mins, p->mins);
6020                         VectorCopy(maxs, p->maxs);
6021                 }
6022                 else
6023                 {
6024                         // We're totally screwed.
6025                         return;
6026                 }
6027         }
6028         else
6029         {
6030                 // merge mins/maxs when we're adding this surface to the plane
6031                 p->mins[0] = min(p->mins[0], mins[0]);
6032                 p->mins[1] = min(p->mins[1], mins[1]);
6033                 p->mins[2] = min(p->mins[2], mins[2]);
6034                 p->maxs[0] = max(p->maxs[0], maxs[0]);
6035                 p->maxs[1] = max(p->maxs[1], maxs[1]);
6036                 p->maxs[2] = max(p->maxs[2], maxs[2]);
6037         }
6038         // merge this surface's materialflags into the waterplane
6039         p->materialflags |= t->currentmaterialflags;
6040         if(!(p->materialflags & MATERIALFLAG_CAMERA))
6041         {
6042                 // merge this surface's PVS into the waterplane
6043                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
6044                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
6045                 {
6046                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
6047                         p->pvsvalid = true;
6048                 }
6049         }
6050 }
6051
6052 extern cvar_t r_drawparticles;
6053 extern cvar_t r_drawdecals;
6054
6055 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6056 {
6057         int myscissor[4];
6058         r_refdef_view_t originalview;
6059         r_refdef_view_t myview;
6060         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;
6061         r_waterstate_waterplane_t *p;
6062         vec3_t visorigin;
6063         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;
6064         char vabuf[1024];
6065
6066         originalview = r_refdef.view;
6067
6068         // lowquality hack, temporarily shut down some cvars and restore afterwards
6069         qualityreduction = r_water_lowquality.integer;
6070         if (qualityreduction > 0)
6071         {
6072                 if (qualityreduction >= 1)
6073                 {
6074                         old_r_shadows = r_shadows.integer;
6075                         old_r_worldrtlight = r_shadow_realtime_world.integer;
6076                         old_r_dlight = r_shadow_realtime_dlight.integer;
6077                         Cvar_SetValueQuick(&r_shadows, 0);
6078                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
6079                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
6080                 }
6081                 if (qualityreduction >= 2)
6082                 {
6083                         old_r_dynamic = r_dynamic.integer;
6084                         old_r_particles = r_drawparticles.integer;
6085                         old_r_decals = r_drawdecals.integer;
6086                         Cvar_SetValueQuick(&r_dynamic, 0);
6087                         Cvar_SetValueQuick(&r_drawparticles, 0);
6088                         Cvar_SetValueQuick(&r_drawdecals, 0);
6089                 }
6090         }
6091
6092         // make sure enough textures are allocated
6093         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6094         {
6095                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6096                 {
6097                         if (!p->texture_refraction)
6098                                 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);
6099                         if (!p->texture_refraction)
6100                                 goto error;
6101                         if (usewaterfbo)
6102                         {
6103                                 if (r_fb.water.depthtexture == NULL)
6104                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6105                                 if (p->fbo_refraction == 0)
6106                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
6107                         }
6108                 }
6109                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6110                 {
6111                         if (!p->texture_camera)
6112                                 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);
6113                         if (!p->texture_camera)
6114                                 goto error;
6115                         if (usewaterfbo)
6116                         {
6117                                 if (r_fb.water.depthtexture == NULL)
6118                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6119                                 if (p->fbo_camera == 0)
6120                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
6121                         }
6122                 }
6123
6124                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6125                 {
6126                         if (!p->texture_reflection)
6127                                 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);
6128                         if (!p->texture_reflection)
6129                                 goto error;
6130                         if (usewaterfbo)
6131                         {
6132                                 if (r_fb.water.depthtexture == NULL)
6133                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6134                                 if (p->fbo_reflection == 0)
6135                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
6136                         }
6137                 }
6138         }
6139
6140         // render views
6141         r_refdef.view = originalview;
6142         r_refdef.view.showdebug = false;
6143         r_refdef.view.width = r_fb.water.waterwidth;
6144         r_refdef.view.height = r_fb.water.waterheight;
6145         r_refdef.view.useclipplane = true;
6146         myview = r_refdef.view;
6147         r_fb.water.renderingscene = true;
6148         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
6149         {
6150                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
6151                 {
6152                         r_refdef.view = myview;
6153                         if(r_water_scissormode.integer)
6154                         {
6155                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6156                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6157                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6158                         }
6159
6160                         // render reflected scene and copy into texture
6161                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
6162                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
6163                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
6164                         r_refdef.view.clipplane = p->plane;
6165                         // reverse the cullface settings for this render
6166                         r_refdef.view.cullface_front = GL_FRONT;
6167                         r_refdef.view.cullface_back = GL_BACK;
6168                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
6169                         {
6170                                 r_refdef.view.usecustompvs = true;
6171                                 if (p->pvsvalid)
6172                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6173                                 else
6174                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
6175                         }
6176
6177                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 2) && !chase_active.integer);
6178                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6179                         R_ClearScreen(r_refdef.fogenabled);
6180                         if(r_water_scissormode.integer & 2)
6181                                 R_View_UpdateWithScissor(myscissor);
6182                         else
6183                                 R_View_Update();
6184                         R_AnimCache_CacheVisibleEntities();
6185                         if(r_water_scissormode.integer & 1)
6186                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6187                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
6188
6189                         if (!p->fbo_reflection)
6190                                 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);
6191                         r_fb.water.hideplayer = false;
6192                 }
6193
6194                 // render the normal view scene and copy into texture
6195                 // (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)
6196                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
6197                 {
6198                         r_refdef.view = myview;
6199                         if(r_water_scissormode.integer)
6200                         {
6201                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6202                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6203                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6204                         }
6205
6206                         r_fb.water.hideplayer = ((r_water_hideplayer.integer >= 1) && !chase_active.integer);
6207
6208                         r_refdef.view.clipplane = p->plane;
6209                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6210                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6211
6212                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6213                         {
6214                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6215                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6216                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6217                                 R_RenderView_UpdateViewVectors();
6218                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6219                                 {
6220                                         r_refdef.view.usecustompvs = true;
6221                                         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);
6222                                 }
6223                         }
6224
6225                         PlaneClassify(&r_refdef.view.clipplane);
6226
6227                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6228                         R_ClearScreen(r_refdef.fogenabled);
6229                         if(r_water_scissormode.integer & 2)
6230                                 R_View_UpdateWithScissor(myscissor);
6231                         else
6232                                 R_View_Update();
6233                         R_AnimCache_CacheVisibleEntities();
6234                         if(r_water_scissormode.integer & 1)
6235                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6236                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6237
6238                         if (!p->fbo_refraction)
6239                                 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);
6240                         r_fb.water.hideplayer = false;
6241                 }
6242                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6243                 {
6244                         r_refdef.view = myview;
6245
6246                         r_refdef.view.clipplane = p->plane;
6247                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6248                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6249
6250                         r_refdef.view.width = r_fb.water.camerawidth;
6251                         r_refdef.view.height = r_fb.water.cameraheight;
6252                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6253                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6254                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6255                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6256
6257                         if(p->camera_entity)
6258                         {
6259                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6260                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6261                         }
6262
6263                         // note: all of the view is used for displaying... so
6264                         // there is no use in scissoring
6265
6266                         // reverse the cullface settings for this render
6267                         r_refdef.view.cullface_front = GL_FRONT;
6268                         r_refdef.view.cullface_back = GL_BACK;
6269                         // also reverse the view matrix
6270                         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
6271                         R_RenderView_UpdateViewVectors();
6272                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6273                         {
6274                                 r_refdef.view.usecustompvs = true;
6275                                 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);
6276                         }
6277                         
6278                         // camera needs no clipplane
6279                         r_refdef.view.useclipplane = false;
6280
6281                         PlaneClassify(&r_refdef.view.clipplane);
6282
6283                         r_fb.water.hideplayer = false;
6284
6285                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6286                         R_ClearScreen(r_refdef.fogenabled);
6287                         R_View_Update();
6288                         R_AnimCache_CacheVisibleEntities();
6289                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6290
6291                         if (!p->fbo_camera)
6292                                 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);
6293                         r_fb.water.hideplayer = false;
6294                 }
6295
6296         }
6297         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6298         r_fb.water.renderingscene = false;
6299         r_refdef.view = originalview;
6300         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6301         if (!r_fb.water.depthtexture)
6302                 R_ClearScreen(r_refdef.fogenabled);
6303         R_View_Update();
6304         R_AnimCache_CacheVisibleEntities();
6305         goto finish;
6306 error:
6307         r_refdef.view = originalview;
6308         r_fb.water.renderingscene = false;
6309         Cvar_SetValueQuick(&r_water, 0);
6310         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6311 finish:
6312         // lowquality hack, restore cvars
6313         if (qualityreduction > 0)
6314         {
6315                 if (qualityreduction >= 1)
6316                 {
6317                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6318                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6319                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6320                 }
6321                 if (qualityreduction >= 2)
6322                 {
6323                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6324                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6325                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6326                 }
6327         }
6328 }
6329
6330 static void R_Bloom_StartFrame(void)
6331 {
6332         int i;
6333         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6334         int viewwidth, viewheight;
6335         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6336         textype_t textype = TEXTYPE_COLORBUFFER;
6337
6338         switch (vid.renderpath)
6339         {
6340         case RENDERPATH_GL20:
6341                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6342                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6343                 {
6344                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6345                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6346                 }
6347                 break;
6348         case RENDERPATH_GL11:
6349         case RENDERPATH_GL13:
6350         case RENDERPATH_GLES1:
6351         case RENDERPATH_GLES2:
6352         case RENDERPATH_D3D9:
6353         case RENDERPATH_D3D10:
6354         case RENDERPATH_D3D11:
6355                 r_fb.usedepthtextures = false;
6356                 break;
6357         case RENDERPATH_SOFT:
6358                 r_fb.usedepthtextures = true;
6359                 break;
6360         }
6361
6362         if (r_viewscale_fpsscaling.integer)
6363         {
6364                 double actualframetime;
6365                 double targetframetime;
6366                 double adjust;
6367                 actualframetime = r_refdef.lastdrawscreentime;
6368                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6369                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6370                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6371                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6372                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6373                 viewscalefpsadjusted += adjust;
6374                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6375         }
6376         else
6377                 viewscalefpsadjusted = 1.0f;
6378
6379         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6380
6381         switch(vid.renderpath)
6382         {
6383         case RENDERPATH_GL20:
6384         case RENDERPATH_D3D9:
6385         case RENDERPATH_D3D10:
6386         case RENDERPATH_D3D11:
6387         case RENDERPATH_SOFT:
6388         case RENDERPATH_GLES2:
6389                 break;
6390         case RENDERPATH_GL11:
6391         case RENDERPATH_GL13:
6392         case RENDERPATH_GLES1:
6393                 return;
6394         }
6395
6396         // set bloomwidth and bloomheight to the bloom resolution that will be
6397         // used (often less than the screen resolution for faster rendering)
6398         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6399         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6400         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6401         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6402         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6403
6404         // calculate desired texture sizes
6405         if (vid.support.arb_texture_non_power_of_two)
6406         {
6407                 screentexturewidth = vid.width;
6408                 screentextureheight = vid.height;
6409                 bloomtexturewidth = r_fb.bloomwidth;
6410                 bloomtextureheight = r_fb.bloomheight;
6411         }
6412         else
6413         {
6414                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6415                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6416                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6417                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6418         }
6419
6420         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))
6421         {
6422                 Cvar_SetValueQuick(&r_bloom, 0);
6423                 Cvar_SetValueQuick(&r_motionblur, 0);
6424                 Cvar_SetValueQuick(&r_damageblur, 0);
6425         }
6426
6427         if (!((r_glsl_postprocess.integer || r_fxaa.integer) || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6428          && !r_bloom.integer
6429          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6430          && !useviewfbo
6431          && r_viewscale.value == 1.0f
6432          && !r_viewscale_fpsscaling.integer)
6433                 screentexturewidth = screentextureheight = 0;
6434         if (!r_bloom.integer)
6435                 bloomtexturewidth = bloomtextureheight = 0;
6436
6437         // allocate textures as needed
6438         if (r_fb.screentexturewidth != screentexturewidth
6439          || r_fb.screentextureheight != screentextureheight
6440          || r_fb.bloomtexturewidth != bloomtexturewidth
6441          || r_fb.bloomtextureheight != bloomtextureheight
6442          || r_fb.textype != textype
6443          || useviewfbo != (r_fb.fbo != 0))
6444         {
6445                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6446                 {
6447                         if (r_fb.bloomtexture[i])
6448                                 R_FreeTexture(r_fb.bloomtexture[i]);
6449                         r_fb.bloomtexture[i] = NULL;
6450
6451                         if (r_fb.bloomfbo[i])
6452                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6453                         r_fb.bloomfbo[i] = 0;
6454                 }
6455
6456                 if (r_fb.fbo)
6457                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6458                 r_fb.fbo = 0;
6459
6460                 if (r_fb.colortexture)
6461                         R_FreeTexture(r_fb.colortexture);
6462                 r_fb.colortexture = NULL;
6463
6464                 if (r_fb.depthtexture)
6465                         R_FreeTexture(r_fb.depthtexture);
6466                 r_fb.depthtexture = NULL;
6467
6468                 if (r_fb.ghosttexture)
6469                         R_FreeTexture(r_fb.ghosttexture);
6470                 r_fb.ghosttexture = NULL;
6471
6472                 r_fb.screentexturewidth = screentexturewidth;
6473                 r_fb.screentextureheight = screentextureheight;
6474                 r_fb.bloomtexturewidth = bloomtexturewidth;
6475                 r_fb.bloomtextureheight = bloomtextureheight;
6476                 r_fb.textype = textype;
6477
6478                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6479                 {
6480                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6481                                 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);
6482                         r_fb.ghosttexture_valid = false;
6483                         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);
6484                         if (useviewfbo)
6485                         {
6486                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6487                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6488                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6489                         }
6490                 }
6491
6492                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6493                 {
6494                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6495                         {
6496                                 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);
6497                                 if (useviewfbo)
6498                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6499                         }
6500                 }
6501         }
6502
6503         // bloom texture is a different resolution
6504         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6505         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6506         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6507         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6508         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6509
6510         // set up a texcoord array for the full resolution screen image
6511         // (we have to keep this around to copy back during final render)
6512         r_fb.screentexcoord2f[0] = 0;
6513         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6514         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6515         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6516         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6517         r_fb.screentexcoord2f[5] = 0;
6518         r_fb.screentexcoord2f[6] = 0;
6519         r_fb.screentexcoord2f[7] = 0;
6520
6521         if(r_fb.fbo) 
6522         {
6523                 for (i = 1;i < 8;i += 2)
6524                 {
6525                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6526                 }
6527         }
6528
6529         // set up a texcoord array for the reduced resolution bloom image
6530         // (which will be additive blended over the screen image)
6531         r_fb.bloomtexcoord2f[0] = 0;
6532         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6533         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6534         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6535         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6536         r_fb.bloomtexcoord2f[5] = 0;
6537         r_fb.bloomtexcoord2f[6] = 0;
6538         r_fb.bloomtexcoord2f[7] = 0;
6539
6540         switch(vid.renderpath)
6541         {
6542         case RENDERPATH_GL11:
6543         case RENDERPATH_GL13:
6544         case RENDERPATH_GL20:
6545         case RENDERPATH_SOFT:
6546         case RENDERPATH_GLES1:
6547         case RENDERPATH_GLES2:
6548                 break;
6549         case RENDERPATH_D3D9:
6550         case RENDERPATH_D3D10:
6551         case RENDERPATH_D3D11:
6552                 for (i = 0;i < 4;i++)
6553                 {
6554                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6555                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6556                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6557                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6558                 }
6559                 break;
6560         }
6561
6562         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6563
6564         if (r_fb.fbo)
6565                 r_refdef.view.clear = true;
6566 }
6567
6568 static void R_Bloom_MakeTexture(void)
6569 {
6570         int x, range, dir;
6571         float xoffset, yoffset, r, brighten;
6572         rtexture_t *intex;
6573         float colorscale = r_bloom_colorscale.value;
6574
6575         r_refdef.stats[r_stat_bloom]++;
6576     
6577 #if 0
6578     // this copy is unnecessary since it happens in R_BlendView already
6579         if (!r_fb.fbo)
6580         {
6581                 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);
6582                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6583         }
6584 #endif
6585
6586         // scale down screen texture to the bloom texture size
6587         CHECKGLERROR
6588         r_fb.bloomindex = 0;
6589         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6590         R_SetViewport(&r_fb.bloomviewport);
6591         GL_DepthTest(false);
6592         GL_BlendFunc(GL_ONE, GL_ZERO);
6593         GL_Color(colorscale, colorscale, colorscale, 1);
6594         // 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...
6595         switch(vid.renderpath)
6596         {
6597         case RENDERPATH_GL11:
6598         case RENDERPATH_GL13:
6599         case RENDERPATH_GL20:
6600         case RENDERPATH_GLES1:
6601         case RENDERPATH_GLES2:
6602         case RENDERPATH_SOFT:
6603                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6604                 break;
6605         case RENDERPATH_D3D9:
6606         case RENDERPATH_D3D10:
6607         case RENDERPATH_D3D11:
6608                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6609                 break;
6610         }
6611         // TODO: do boxfilter scale-down in shader?
6612         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6613         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6614         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6615
6616         // we now have a properly scaled bloom image
6617         if (!r_fb.bloomfbo[r_fb.bloomindex])
6618         {
6619                 // copy it into the bloom texture
6620                 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);
6621                 r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6622         }
6623
6624         // multiply bloom image by itself as many times as desired
6625         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6626         {
6627                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6628                 r_fb.bloomindex ^= 1;
6629                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6630                 x *= 2;
6631                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6632                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6633                 {
6634                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6635                         GL_Color(r,r,r,1); // apply fix factor
6636                 }
6637                 else
6638                 {
6639                         if(x <= 2)
6640                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6641                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6642                         GL_Color(1,1,1,1); // no fix factor supported here
6643                 }
6644                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6645                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6646                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6647                 r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6648
6649                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6650                 {
6651                         // copy the darkened image to a texture
6652                         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);
6653                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6654                 }
6655         }
6656
6657         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6658         brighten = r_bloom_brighten.value;
6659         brighten = sqrt(brighten);
6660         if(range >= 1)
6661                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6662
6663         for (dir = 0;dir < 2;dir++)
6664         {
6665                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6666                 r_fb.bloomindex ^= 1;
6667                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6668                 // blend on at multiple vertical offsets to achieve a vertical blur
6669                 // TODO: do offset blends using GLSL
6670                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6671                 GL_BlendFunc(GL_ONE, GL_ZERO);
6672                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6673                 for (x = -range;x <= range;x++)
6674                 {
6675                         if (!dir){xoffset = 0;yoffset = x;}
6676                         else {xoffset = x;yoffset = 0;}
6677                         xoffset /= (float)r_fb.bloomtexturewidth;
6678                         yoffset /= (float)r_fb.bloomtextureheight;
6679                         // compute a texcoord array with the specified x and y offset
6680                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6681                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6682                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6683                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6684                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6685                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6686                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6687                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6688                         // this r value looks like a 'dot' particle, fading sharply to
6689                         // black at the edges
6690                         // (probably not realistic but looks good enough)
6691                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6692                         //r = brighten/(range*2+1);
6693                         r = brighten / (range * 2 + 1);
6694                         if(range >= 1)
6695                                 r *= (1 - x*x/(float)(range*range));
6696                         GL_Color(r, r, r, 1);
6697                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6698                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6699                         r_refdef.stats[r_stat_bloom_drawpixels] += r_fb.bloomwidth * r_fb.bloomheight;
6700                         GL_BlendFunc(GL_ONE, GL_ONE);
6701                 }
6702
6703                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6704                 {
6705                         // copy the vertically or horizontally blurred bloom view to a texture
6706                         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);
6707                         r_refdef.stats[r_stat_bloom_copypixels] += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6708                 }
6709         }
6710 }
6711
6712 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6713 {
6714         unsigned int permutation;
6715         float uservecs[4][4];
6716
6717         R_EntityMatrix(&identitymatrix);
6718
6719         switch (vid.renderpath)
6720         {
6721         case RENDERPATH_GL20:
6722         case RENDERPATH_D3D9:
6723         case RENDERPATH_D3D10:
6724         case RENDERPATH_D3D11:
6725         case RENDERPATH_SOFT:
6726         case RENDERPATH_GLES2:
6727                 permutation =
6728                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6729                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6730                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6731                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6732                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6733
6734                 if (r_fb.colortexture)
6735                 {
6736                         if (!r_fb.fbo)
6737                         {
6738                                 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);
6739                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6740                         }
6741
6742                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6743                         {
6744                                 // declare variables
6745                                 float blur_factor, blur_mouseaccel, blur_velocity;
6746                                 static float blur_average; 
6747                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6748
6749                                 // set a goal for the factoring
6750                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6751                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6752                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6753                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6754                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6755                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6756
6757                                 // from the goal, pick an averaged value between goal and last value
6758                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6759                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6760
6761                                 // enforce minimum amount of blur 
6762                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6763
6764                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6765
6766                                 // calculate values into a standard alpha
6767                                 cl.motionbluralpha = 1 - exp(-
6768                                                 (
6769                                                  (r_motionblur.value * blur_factor / 80)
6770                                                  +
6771                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6772                                                 )
6773                                                 /
6774                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6775                                           );
6776
6777                                 // randomization for the blur value to combat persistent ghosting
6778                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6779                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6780
6781                                 // apply the blur
6782                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6783                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6784                                 {
6785                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6786                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6787                                         switch(vid.renderpath)
6788                                         {
6789                                         case RENDERPATH_GL11:
6790                                         case RENDERPATH_GL13:
6791                                         case RENDERPATH_GL20:
6792                                         case RENDERPATH_GLES1:
6793                                         case RENDERPATH_GLES2:
6794                                         case RENDERPATH_SOFT:
6795                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6796                                                 break;
6797                                         case RENDERPATH_D3D9:
6798                                         case RENDERPATH_D3D10:
6799                                         case RENDERPATH_D3D11:
6800                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6801                                                 break;
6802                                         }
6803                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6804                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6805                                         r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6806                                 }
6807
6808                                 // updates old view angles for next pass
6809                                 VectorCopy(cl.viewangles, blur_oldangles);
6810
6811                                 // copy view into the ghost texture
6812                                 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);
6813                                 r_refdef.stats[r_stat_bloom_copypixels] += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6814                                 r_fb.ghosttexture_valid = true;
6815                         }
6816                 }
6817                 else
6818                 {
6819                         // no r_fb.colortexture means we're rendering to the real fb
6820                         // we may still have to do view tint...
6821                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6822                         {
6823                                 // apply a color tint to the whole view
6824                                 R_ResetViewRendering2D(0, NULL, NULL);
6825                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6826                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6827                                 R_SetupShader_Generic_NoTexture(false, true);
6828                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6829                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6830                         }
6831                         break; // no screen processing, no bloom, skip it
6832                 }
6833
6834                 if (r_fb.bloomtexture[0])
6835                 {
6836                         // make the bloom texture
6837                         R_Bloom_MakeTexture();
6838                 }
6839
6840 #if _MSC_VER >= 1400
6841 #define sscanf sscanf_s
6842 #endif
6843                 memset(uservecs, 0, sizeof(uservecs));
6844                 if (r_glsl_postprocess_uservec1_enable.integer)
6845                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6846                 if (r_glsl_postprocess_uservec2_enable.integer)
6847                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6848                 if (r_glsl_postprocess_uservec3_enable.integer)
6849                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6850                 if (r_glsl_postprocess_uservec4_enable.integer)
6851                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6852
6853                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6854                 GL_Color(1, 1, 1, 1);
6855                 GL_BlendFunc(GL_ONE, GL_ZERO);
6856
6857                 switch(vid.renderpath)
6858                 {
6859                 case RENDERPATH_GL20:
6860                 case RENDERPATH_GLES2:
6861                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6862                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6863                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6864                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6865                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6866                         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]);
6867                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6868                         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]);
6869                         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]);
6870                         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]);
6871                         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]);
6872                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6873                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6874                         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);
6875                         break;
6876                 case RENDERPATH_D3D9:
6877 #ifdef SUPPORTD3D
6878                         // 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...
6879                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6880                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6881                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6882                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6883                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6884                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6885                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6886                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6887                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6888                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6889                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6890                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6891                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6892                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6893 #endif
6894                         break;
6895                 case RENDERPATH_D3D10:
6896                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6897                         break;
6898                 case RENDERPATH_D3D11:
6899                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6900                         break;
6901                 case RENDERPATH_SOFT:
6902                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6903                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6904                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6905                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6906                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6907                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6908                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6909                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6910                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6911                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6912                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6913                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6914                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6915                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6916                         break;
6917                 default:
6918                         break;
6919                 }
6920                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6921                 r_refdef.stats[r_stat_bloom_drawpixels] += r_refdef.view.width * r_refdef.view.height;
6922                 break;
6923         case RENDERPATH_GL11:
6924         case RENDERPATH_GL13:
6925         case RENDERPATH_GLES1:
6926                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6927                 {
6928                         // apply a color tint to the whole view
6929                         R_ResetViewRendering2D(0, NULL, NULL);
6930                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6931                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6932                         R_SetupShader_Generic_NoTexture(false, true);
6933                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6934                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6935                 }
6936                 break;
6937         }
6938 }
6939
6940 matrix4x4_t r_waterscrollmatrix;
6941
6942 void R_UpdateFog(void)
6943 {
6944         // Nehahra fog
6945         if (gamemode == GAME_NEHAHRA)
6946         {
6947                 if (gl_fogenable.integer)
6948                 {
6949                         r_refdef.oldgl_fogenable = true;
6950                         r_refdef.fog_density = gl_fogdensity.value;
6951                         r_refdef.fog_red = gl_fogred.value;
6952                         r_refdef.fog_green = gl_foggreen.value;
6953                         r_refdef.fog_blue = gl_fogblue.value;
6954                         r_refdef.fog_alpha = 1;
6955                         r_refdef.fog_start = 0;
6956                         r_refdef.fog_end = gl_skyclip.value;
6957                         r_refdef.fog_height = 1<<30;
6958                         r_refdef.fog_fadedepth = 128;
6959                 }
6960                 else if (r_refdef.oldgl_fogenable)
6961                 {
6962                         r_refdef.oldgl_fogenable = false;
6963                         r_refdef.fog_density = 0;
6964                         r_refdef.fog_red = 0;
6965                         r_refdef.fog_green = 0;
6966                         r_refdef.fog_blue = 0;
6967                         r_refdef.fog_alpha = 0;
6968                         r_refdef.fog_start = 0;
6969                         r_refdef.fog_end = 0;
6970                         r_refdef.fog_height = 1<<30;
6971                         r_refdef.fog_fadedepth = 128;
6972                 }
6973         }
6974
6975         // fog parms
6976         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6977         r_refdef.fog_start = max(0, r_refdef.fog_start);
6978         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6979
6980         if (r_refdef.fog_density && r_drawfog.integer)
6981         {
6982                 r_refdef.fogenabled = true;
6983                 // this is the point where the fog reaches 0.9986 alpha, which we
6984                 // consider a good enough cutoff point for the texture
6985                 // (0.9986 * 256 == 255.6)
6986                 if (r_fog_exp2.integer)
6987                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6988                 else
6989                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6990                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6991                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6992                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6993                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6994                         R_BuildFogHeightTexture();
6995                 // fog color was already set
6996                 // update the fog texture
6997                 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)
6998                         R_BuildFogTexture();
6999                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
7000                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
7001         }
7002         else
7003                 r_refdef.fogenabled = false;
7004
7005         // fog color
7006         if (r_refdef.fog_density)
7007         {
7008                 r_refdef.fogcolor[0] = r_refdef.fog_red;
7009                 r_refdef.fogcolor[1] = r_refdef.fog_green;
7010                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
7011
7012                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
7013                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
7014                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
7015                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
7016
7017                 {
7018                         vec3_t fogvec;
7019                         VectorCopy(r_refdef.fogcolor, fogvec);
7020                         //   color.rgb *= ContrastBoost * SceneBrightness;
7021                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
7022                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
7023                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
7024                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
7025                 }
7026         }
7027 }
7028
7029 void R_UpdateVariables(void)
7030 {
7031         R_Textures_Frame();
7032
7033         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
7034
7035         r_refdef.farclip = r_farclip_base.value;
7036         if (r_refdef.scene.worldmodel)
7037                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
7038         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
7039
7040         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
7041                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
7042         r_refdef.polygonfactor = 0;
7043         r_refdef.polygonoffset = 0;
7044         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7045         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
7046
7047         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
7048         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
7049         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
7050         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
7051         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
7052         if (FAKELIGHT_ENABLED)
7053         {
7054                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
7055         }
7056         else if (r_refdef.scene.worldmodel)
7057         {
7058                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
7059         }
7060         if (r_showsurfaces.integer)
7061         {
7062                 r_refdef.scene.rtworld = false;
7063                 r_refdef.scene.rtworldshadows = false;
7064                 r_refdef.scene.rtdlight = false;
7065                 r_refdef.scene.rtdlightshadows = false;
7066                 r_refdef.lightmapintensity = 0;
7067         }
7068
7069         r_gpuskeletal = false;
7070         switch(vid.renderpath)
7071         {
7072         case RENDERPATH_GL20:
7073                 r_gpuskeletal = vid.support.arb_uniform_buffer_object && r_glsl_skeletal.integer && !r_showsurfaces.integer; // FIXME add r_showsurfaces support to GLSL skeletal!
7074         case RENDERPATH_D3D9:
7075         case RENDERPATH_D3D10:
7076         case RENDERPATH_D3D11:
7077         case RENDERPATH_SOFT:
7078         case RENDERPATH_GLES2:
7079                 if(v_glslgamma.integer && !vid_gammatables_trivial)
7080                 {
7081                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
7082                         {
7083                                 // build GLSL gamma texture
7084 #define RAMPWIDTH 256
7085                                 unsigned short ramp[RAMPWIDTH * 3];
7086                                 unsigned char rampbgr[RAMPWIDTH][4];
7087                                 int i;
7088
7089                                 r_texture_gammaramps_serial = vid_gammatables_serial;
7090
7091                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
7092                                 for(i = 0; i < RAMPWIDTH; ++i)
7093                                 {
7094                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7095                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
7096                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
7097                                         rampbgr[i][3] = 0;
7098                                 }
7099                                 if (r_texture_gammaramps)
7100                                 {
7101                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
7102                                 }
7103                                 else
7104                                 {
7105                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
7106                                 }
7107                         }
7108                 }
7109                 else
7110                 {
7111                         // remove GLSL gamma texture
7112                 }
7113                 break;
7114         case RENDERPATH_GL11:
7115         case RENDERPATH_GL13:
7116         case RENDERPATH_GLES1:
7117                 break;
7118         }
7119 }
7120
7121 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
7122 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
7123 /*
7124 ================
7125 R_SelectScene
7126 ================
7127 */
7128 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
7129         if( scenetype != r_currentscenetype ) {
7130                 // store the old scenetype
7131                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
7132                 r_currentscenetype = scenetype;
7133                 // move in the new scene
7134                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
7135         }
7136 }
7137
7138 /*
7139 ================
7140 R_GetScenePointer
7141 ================
7142 */
7143 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
7144 {
7145         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
7146         if( scenetype == r_currentscenetype ) {
7147                 return &r_refdef.scene;
7148         } else {
7149                 return &r_scenes_store[ scenetype ];
7150         }
7151 }
7152
7153 static int R_SortEntities_Compare(const void *ap, const void *bp)
7154 {
7155         const entity_render_t *a = *(const entity_render_t **)ap;
7156         const entity_render_t *b = *(const entity_render_t **)bp;
7157
7158         // 1. compare model
7159         if(a->model < b->model)
7160                 return -1;
7161         if(a->model > b->model)
7162                 return +1;
7163
7164         // 2. compare skin
7165         // TODO possibly calculate the REAL skinnum here first using
7166         // skinscenes?
7167         if(a->skinnum < b->skinnum)
7168                 return -1;
7169         if(a->skinnum > b->skinnum)
7170                 return +1;
7171
7172         // everything we compared is equal
7173         return 0;
7174 }
7175 static void R_SortEntities(void)
7176 {
7177         // below or equal 2 ents, sorting never gains anything
7178         if(r_refdef.scene.numentities <= 2)
7179                 return;
7180         // sort
7181         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
7182 }
7183
7184 /*
7185 ================
7186 R_RenderView
7187 ================
7188 */
7189 int dpsoftrast_test;
7190 extern cvar_t r_shadow_bouncegrid;
7191 void R_RenderView(void)
7192 {
7193         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
7194         int fbo;
7195         rtexture_t *depthtexture;
7196         rtexture_t *colortexture;
7197
7198         dpsoftrast_test = r_test.integer;
7199
7200         if (r_timereport_active)
7201                 R_TimeReport("start");
7202         r_textureframe++; // used only by R_GetCurrentTexture
7203         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7204
7205         if(R_CompileShader_CheckStaticParms())
7206                 R_GLSL_Restart_f();
7207
7208         if (!r_drawentities.integer)
7209                 r_refdef.scene.numentities = 0;
7210         else if (r_sortentities.integer)
7211                 R_SortEntities();
7212
7213         R_AnimCache_ClearCache();
7214
7215         /* adjust for stereo display */
7216         if(R_Stereo_Active())
7217         {
7218                 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);
7219                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7220         }
7221
7222         if (r_refdef.view.isoverlay)
7223         {
7224                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7225                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7226                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7227                 R_TimeReport("depthclear");
7228
7229                 r_refdef.view.showdebug = false;
7230
7231                 r_fb.water.enabled = false;
7232                 r_fb.water.numwaterplanes = 0;
7233
7234                 R_RenderScene(0, NULL, NULL);
7235
7236                 r_refdef.view.matrix = originalmatrix;
7237
7238                 CHECKGLERROR
7239                 return;
7240         }
7241
7242         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7243         {
7244                 r_refdef.view.matrix = originalmatrix;
7245                 return;
7246         }
7247
7248         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7249
7250         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7251                 // in sRGB fallback, behave similar to true sRGB: convert this
7252                 // value from linear to sRGB
7253                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7254
7255         R_RenderView_UpdateViewVectors();
7256
7257         R_Shadow_UpdateWorldLightSelection();
7258
7259         R_Bloom_StartFrame();
7260
7261         // apply bloom brightness offset
7262         if(r_fb.bloomtexture[0])
7263                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7264
7265         R_Water_StartFrame();
7266
7267         // now we probably have an fbo to render into
7268         fbo = r_fb.fbo;
7269         depthtexture = r_fb.depthtexture;
7270         colortexture = r_fb.colortexture;
7271
7272         CHECKGLERROR
7273         if (r_timereport_active)
7274                 R_TimeReport("viewsetup");
7275
7276         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7277
7278         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7279         {
7280                 R_ClearScreen(r_refdef.fogenabled);
7281                 if (r_timereport_active)
7282                         R_TimeReport("viewclear");
7283         }
7284         r_refdef.view.clear = true;
7285
7286         r_refdef.view.showdebug = true;
7287
7288         R_View_Update();
7289         if (r_timereport_active)
7290                 R_TimeReport("visibility");
7291
7292         R_AnimCache_CacheVisibleEntities();
7293         if (r_timereport_active)
7294                 R_TimeReport("animcache");
7295
7296         R_Shadow_UpdateBounceGridTexture();
7297         if (r_timereport_active && r_shadow_bouncegrid.integer)
7298                 R_TimeReport("bouncegrid");
7299
7300         r_fb.water.numwaterplanes = 0;
7301         if (r_fb.water.enabled)
7302                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7303
7304         R_RenderScene(fbo, depthtexture, colortexture);
7305         r_fb.water.numwaterplanes = 0;
7306
7307         R_BlendView(fbo, depthtexture, colortexture);
7308         if (r_timereport_active)
7309                 R_TimeReport("blendview");
7310
7311         GL_Scissor(0, 0, vid.width, vid.height);
7312         GL_ScissorTest(false);
7313
7314         r_refdef.view.matrix = originalmatrix;
7315
7316         CHECKGLERROR
7317 }
7318
7319 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7320 {
7321         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7322         {
7323                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7324                 if (r_timereport_active)
7325                         R_TimeReport("waterworld");
7326         }
7327
7328         // don't let sound skip if going slow
7329         if (r_refdef.scene.extraupdate)
7330                 S_ExtraUpdate ();
7331
7332         R_DrawModelsAddWaterPlanes();
7333         if (r_timereport_active)
7334                 R_TimeReport("watermodels");
7335
7336         if (r_fb.water.numwaterplanes)
7337         {
7338                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7339                 if (r_timereport_active)
7340                         R_TimeReport("waterscenes");
7341         }
7342 }
7343
7344 extern cvar_t cl_locs_show;
7345 static void R_DrawLocs(void);
7346 static void R_DrawEntityBBoxes(void);
7347 static void R_DrawModelDecals(void);
7348 extern cvar_t cl_decals_newsystem;
7349 extern qboolean r_shadow_usingdeferredprepass;
7350 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7351 {
7352         qboolean shadowmapping = false;
7353
7354         if (r_timereport_active)
7355                 R_TimeReport("beginscene");
7356
7357         r_refdef.stats[r_stat_renders]++;
7358
7359         R_UpdateFog();
7360
7361         // don't let sound skip if going slow
7362         if (r_refdef.scene.extraupdate)
7363                 S_ExtraUpdate ();
7364
7365         R_MeshQueue_BeginScene();
7366
7367         R_SkyStartFrame();
7368
7369         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);
7370
7371         if (r_timereport_active)
7372                 R_TimeReport("skystartframe");
7373
7374         if (cl.csqc_vidvars.drawworld)
7375         {
7376                 // don't let sound skip if going slow
7377                 if (r_refdef.scene.extraupdate)
7378                         S_ExtraUpdate ();
7379
7380                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7381                 {
7382                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7383                         if (r_timereport_active)
7384                                 R_TimeReport("worldsky");
7385                 }
7386
7387                 if (R_DrawBrushModelsSky() && r_timereport_active)
7388                         R_TimeReport("bmodelsky");
7389
7390                 if (skyrendermasked && skyrenderlater)
7391                 {
7392                         // we have to force off the water clipping plane while rendering sky
7393                         R_SetupView(false, fbo, depthtexture, colortexture);
7394                         R_Sky();
7395                         R_SetupView(true, fbo, depthtexture, colortexture);
7396                         if (r_timereport_active)
7397                                 R_TimeReport("sky");
7398                 }
7399         }
7400
7401         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7402         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7403                 R_Shadow_PrepareModelShadows();
7404         if (r_timereport_active)
7405                 R_TimeReport("preparelights");
7406
7407         if (R_Shadow_ShadowMappingEnabled())
7408                 shadowmapping = true;
7409
7410         if (r_shadow_usingdeferredprepass)
7411                 R_Shadow_DrawPrepass();
7412
7413         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7414         {
7415                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7416                 if (r_timereport_active)
7417                         R_TimeReport("worlddepth");
7418         }
7419         if (r_depthfirst.integer >= 2)
7420         {
7421                 R_DrawModelsDepth();
7422                 if (r_timereport_active)
7423                         R_TimeReport("modeldepth");
7424         }
7425
7426         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7427         {
7428                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7429                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7430                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7431                 // don't let sound skip if going slow
7432                 if (r_refdef.scene.extraupdate)
7433                         S_ExtraUpdate ();
7434         }
7435
7436         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7437         {
7438                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7439                 if (r_timereport_active)
7440                         R_TimeReport("world");
7441         }
7442
7443         // don't let sound skip if going slow
7444         if (r_refdef.scene.extraupdate)
7445                 S_ExtraUpdate ();
7446
7447         R_DrawModels();
7448         if (r_timereport_active)
7449                 R_TimeReport("models");
7450
7451         // don't let sound skip if going slow
7452         if (r_refdef.scene.extraupdate)
7453                 S_ExtraUpdate ();
7454
7455         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7456         {
7457                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7458                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7459                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7460                 // don't let sound skip if going slow
7461                 if (r_refdef.scene.extraupdate)
7462                         S_ExtraUpdate ();
7463         }
7464
7465         if (!r_shadow_usingdeferredprepass)
7466         {
7467                 R_Shadow_DrawLights();
7468                 if (r_timereport_active)
7469                         R_TimeReport("rtlights");
7470         }
7471
7472         // don't let sound skip if going slow
7473         if (r_refdef.scene.extraupdate)
7474                 S_ExtraUpdate ();
7475
7476         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7477         {
7478                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7479                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7480                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7481                 // don't let sound skip if going slow
7482                 if (r_refdef.scene.extraupdate)
7483                         S_ExtraUpdate ();
7484         }
7485
7486         if (cl.csqc_vidvars.drawworld)
7487         {
7488                 if (cl_decals_newsystem.integer)
7489                 {
7490                         R_DrawModelDecals();
7491                         if (r_timereport_active)
7492                                 R_TimeReport("modeldecals");
7493                 }
7494                 else
7495                 {
7496                         R_DrawDecals();
7497                         if (r_timereport_active)
7498                                 R_TimeReport("decals");
7499                 }
7500
7501                 R_DrawParticles();
7502                 if (r_timereport_active)
7503                         R_TimeReport("particles");
7504
7505                 R_DrawExplosions();
7506                 if (r_timereport_active)
7507                         R_TimeReport("explosions");
7508
7509                 R_DrawLightningBeams();
7510                 if (r_timereport_active)
7511                         R_TimeReport("lightning");
7512         }
7513
7514         if (cl.csqc_loaded)
7515                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7516
7517         if (r_refdef.view.showdebug)
7518         {
7519                 if (cl_locs_show.integer)
7520                 {
7521                         R_DrawLocs();
7522                         if (r_timereport_active)
7523                                 R_TimeReport("showlocs");
7524                 }
7525
7526                 if (r_drawportals.integer)
7527                 {
7528                         R_DrawPortals();
7529                         if (r_timereport_active)
7530                                 R_TimeReport("portals");
7531                 }
7532
7533                 if (r_showbboxes.value > 0)
7534                 {
7535                         R_DrawEntityBBoxes();
7536                         if (r_timereport_active)
7537                                 R_TimeReport("bboxes");
7538                 }
7539         }
7540
7541         if (r_transparent.integer)
7542         {
7543                 R_MeshQueue_RenderTransparent();
7544                 if (r_timereport_active)
7545                         R_TimeReport("drawtrans");
7546         }
7547
7548         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))
7549         {
7550                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7551                 if (r_timereport_active)
7552                         R_TimeReport("worlddebug");
7553                 R_DrawModelsDebug();
7554                 if (r_timereport_active)
7555                         R_TimeReport("modeldebug");
7556         }
7557
7558         if (cl.csqc_vidvars.drawworld)
7559         {
7560                 R_Shadow_DrawCoronas();
7561                 if (r_timereport_active)
7562                         R_TimeReport("coronas");
7563         }
7564
7565 #if 0
7566         {
7567                 GL_DepthTest(false);
7568                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7569                 GL_Color(1, 1, 1, 1);
7570                 qglBegin(GL_POLYGON);
7571                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7572                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7573                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7574                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7575                 qglEnd();
7576                 qglBegin(GL_POLYGON);
7577                 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]);
7578                 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]);
7579                 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]);
7580                 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]);
7581                 qglEnd();
7582                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7583         }
7584 #endif
7585
7586         // don't let sound skip if going slow
7587         if (r_refdef.scene.extraupdate)
7588                 S_ExtraUpdate ();
7589 }
7590
7591 static const unsigned short bboxelements[36] =
7592 {
7593         5, 1, 3, 5, 3, 7,
7594         6, 2, 0, 6, 0, 4,
7595         7, 3, 2, 7, 2, 6,
7596         4, 0, 1, 4, 1, 5,
7597         4, 5, 7, 4, 7, 6,
7598         1, 0, 2, 1, 2, 3,
7599 };
7600
7601 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7602 {
7603         int i;
7604         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7605
7606         RSurf_ActiveWorldEntity();
7607
7608         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7609         GL_DepthMask(false);
7610         GL_DepthRange(0, 1);
7611         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7612 //      R_Mesh_ResetTextureState();
7613
7614         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7615         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7616         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7617         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7618         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7619         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7620         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7621         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7622         R_FillColors(color4f, 8, cr, cg, cb, ca);
7623         if (r_refdef.fogenabled)
7624         {
7625                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7626                 {
7627                         f1 = RSurf_FogVertex(v);
7628                         f2 = 1 - f1;
7629                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7630                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7631                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7632                 }
7633         }
7634         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7635         R_Mesh_ResetTextureState();
7636         R_SetupShader_Generic_NoTexture(false, false);
7637         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7638 }
7639
7640 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7641 {
7642         prvm_prog_t *prog = SVVM_prog;
7643         int i;
7644         float color[4];
7645         prvm_edict_t *edict;
7646
7647         // this function draws bounding boxes of server entities
7648         if (!sv.active)
7649                 return;
7650
7651         GL_CullFace(GL_NONE);
7652         R_SetupShader_Generic_NoTexture(false, false);
7653
7654         for (i = 0;i < numsurfaces;i++)
7655         {
7656                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7657                 switch ((int)PRVM_serveredictfloat(edict, solid))
7658                 {
7659                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7660                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7661                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7662                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7663                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7664                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7665                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7666                 }
7667                 color[3] *= r_showbboxes.value;
7668                 color[3] = bound(0, color[3], 1);
7669                 GL_DepthTest(!r_showdisabledepthtest.integer);
7670                 GL_CullFace(r_refdef.view.cullface_front);
7671                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7672         }
7673 }
7674
7675 static void R_DrawEntityBBoxes(void)
7676 {
7677         int i;
7678         prvm_edict_t *edict;
7679         vec3_t center;
7680         prvm_prog_t *prog = SVVM_prog;
7681
7682         // this function draws bounding boxes of server entities
7683         if (!sv.active)
7684                 return;
7685
7686         for (i = 0;i < prog->num_edicts;i++)
7687         {
7688                 edict = PRVM_EDICT_NUM(i);
7689                 if (edict->priv.server->free)
7690                         continue;
7691                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7692                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7693                         continue;
7694                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7695                         continue;
7696                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7697                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7698         }
7699 }
7700
7701 static const int nomodelelement3i[24] =
7702 {
7703         5, 2, 0,
7704         5, 1, 2,
7705         5, 0, 3,
7706         5, 3, 1,
7707         0, 2, 4,
7708         2, 1, 4,
7709         3, 0, 4,
7710         1, 3, 4
7711 };
7712
7713 static const unsigned short nomodelelement3s[24] =
7714 {
7715         5, 2, 0,
7716         5, 1, 2,
7717         5, 0, 3,
7718         5, 3, 1,
7719         0, 2, 4,
7720         2, 1, 4,
7721         3, 0, 4,
7722         1, 3, 4
7723 };
7724
7725 static const float nomodelvertex3f[6*3] =
7726 {
7727         -16,   0,   0,
7728          16,   0,   0,
7729           0, -16,   0,
7730           0,  16,   0,
7731           0,   0, -16,
7732           0,   0,  16
7733 };
7734
7735 static const float nomodelcolor4f[6*4] =
7736 {
7737         0.0f, 0.0f, 0.5f, 1.0f,
7738         0.0f, 0.0f, 0.5f, 1.0f,
7739         0.0f, 0.5f, 0.0f, 1.0f,
7740         0.0f, 0.5f, 0.0f, 1.0f,
7741         0.5f, 0.0f, 0.0f, 1.0f,
7742         0.5f, 0.0f, 0.0f, 1.0f
7743 };
7744
7745 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7746 {
7747         int i;
7748         float f1, f2, *c;
7749         float color4f[6*4];
7750
7751         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);
7752
7753         // this is only called once per entity so numsurfaces is always 1, and
7754         // surfacelist is always {0}, so this code does not handle batches
7755
7756         if (rsurface.ent_flags & RENDER_ADDITIVE)
7757         {
7758                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7759                 GL_DepthMask(false);
7760         }
7761         else if (rsurface.colormod[3] < 1)
7762         {
7763                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7764                 GL_DepthMask(false);
7765         }
7766         else
7767         {
7768                 GL_BlendFunc(GL_ONE, GL_ZERO);
7769                 GL_DepthMask(true);
7770         }
7771         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7772         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7773         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7774         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7775         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7776         for (i = 0, c = color4f;i < 6;i++, c += 4)
7777         {
7778                 c[0] *= rsurface.colormod[0];
7779                 c[1] *= rsurface.colormod[1];
7780                 c[2] *= rsurface.colormod[2];
7781                 c[3] *= rsurface.colormod[3];
7782         }
7783         if (r_refdef.fogenabled)
7784         {
7785                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7786                 {
7787                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7788                         f2 = 1 - f1;
7789                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7790                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7791                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7792                 }
7793         }
7794 //      R_Mesh_ResetTextureState();
7795         R_SetupShader_Generic_NoTexture(false, false);
7796         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7797         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7798 }
7799
7800 void R_DrawNoModel(entity_render_t *ent)
7801 {
7802         vec3_t org;
7803         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7804         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7805                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7806         else
7807                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7808 }
7809
7810 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7811 {
7812         vec3_t right1, right2, diff, normal;
7813
7814         VectorSubtract (org2, org1, normal);
7815
7816         // calculate 'right' vector for start
7817         VectorSubtract (r_refdef.view.origin, org1, diff);
7818         CrossProduct (normal, diff, right1);
7819         VectorNormalize (right1);
7820
7821         // calculate 'right' vector for end
7822         VectorSubtract (r_refdef.view.origin, org2, diff);
7823         CrossProduct (normal, diff, right2);
7824         VectorNormalize (right2);
7825
7826         vert[ 0] = org1[0] + width * right1[0];
7827         vert[ 1] = org1[1] + width * right1[1];
7828         vert[ 2] = org1[2] + width * right1[2];
7829         vert[ 3] = org1[0] - width * right1[0];
7830         vert[ 4] = org1[1] - width * right1[1];
7831         vert[ 5] = org1[2] - width * right1[2];
7832         vert[ 6] = org2[0] - width * right2[0];
7833         vert[ 7] = org2[1] - width * right2[1];
7834         vert[ 8] = org2[2] - width * right2[2];
7835         vert[ 9] = org2[0] + width * right2[0];
7836         vert[10] = org2[1] + width * right2[1];
7837         vert[11] = org2[2] + width * right2[2];
7838 }
7839
7840 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)
7841 {
7842         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7843         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7844         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7845         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7846         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7847         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7848         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7849         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7850         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7851         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7852         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7853         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7854 }
7855
7856 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7857 {
7858         int i;
7859         float *vertex3f;
7860         float v[3];
7861         VectorSet(v, x, y, z);
7862         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7863                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7864                         break;
7865         if (i == mesh->numvertices)
7866         {
7867                 if (mesh->numvertices < mesh->maxvertices)
7868                 {
7869                         VectorCopy(v, vertex3f);
7870                         mesh->numvertices++;
7871                 }
7872                 return mesh->numvertices;
7873         }
7874         else
7875                 return i;
7876 }
7877
7878 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7879 {
7880         int i;
7881         int *e, element[3];
7882         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7883         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7884         e = mesh->element3i + mesh->numtriangles * 3;
7885         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7886         {
7887                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7888                 if (mesh->numtriangles < mesh->maxtriangles)
7889                 {
7890                         *e++ = element[0];
7891                         *e++ = element[1];
7892                         *e++ = element[2];
7893                         mesh->numtriangles++;
7894                 }
7895                 element[1] = element[2];
7896         }
7897 }
7898
7899 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7900 {
7901         int i;
7902         int *e, element[3];
7903         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7904         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7905         e = mesh->element3i + mesh->numtriangles * 3;
7906         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7907         {
7908                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7909                 if (mesh->numtriangles < mesh->maxtriangles)
7910                 {
7911                         *e++ = element[0];
7912                         *e++ = element[1];
7913                         *e++ = element[2];
7914                         mesh->numtriangles++;
7915                 }
7916                 element[1] = element[2];
7917         }
7918 }
7919
7920 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7921 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7922 {
7923         int planenum, planenum2;
7924         int w;
7925         int tempnumpoints;
7926         mplane_t *plane, *plane2;
7927         double maxdist;
7928         double temppoints[2][256*3];
7929         // figure out how large a bounding box we need to properly compute this brush
7930         maxdist = 0;
7931         for (w = 0;w < numplanes;w++)
7932                 maxdist = max(maxdist, fabs(planes[w].dist));
7933         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7934         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7935         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7936         {
7937                 w = 0;
7938                 tempnumpoints = 4;
7939                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7940                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7941                 {
7942                         if (planenum2 == planenum)
7943                                 continue;
7944                         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);
7945                         w = !w;
7946                 }
7947                 if (tempnumpoints < 3)
7948                         continue;
7949                 // generate elements forming a triangle fan for this polygon
7950                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7951         }
7952 }
7953
7954 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)
7955 {
7956         texturelayer_t *layer;
7957         layer = t->currentlayers + t->currentnumlayers++;
7958         layer->type = type;
7959         layer->depthmask = depthmask;
7960         layer->blendfunc1 = blendfunc1;
7961         layer->blendfunc2 = blendfunc2;
7962         layer->texture = texture;
7963         layer->texmatrix = *matrix;
7964         layer->color[0] = r;
7965         layer->color[1] = g;
7966         layer->color[2] = b;
7967         layer->color[3] = a;
7968 }
7969
7970 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7971 {
7972         if(parms[0] == 0 && parms[1] == 0)
7973                 return false;
7974         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7975                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7976                         return false;
7977         return true;
7978 }
7979
7980 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7981 {
7982         double index, f;
7983         index = parms[2] + rsurface.shadertime * parms[3];
7984         index -= floor(index);
7985         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7986         {
7987         default:
7988         case Q3WAVEFUNC_NONE:
7989         case Q3WAVEFUNC_NOISE:
7990         case Q3WAVEFUNC_COUNT:
7991                 f = 0;
7992                 break;
7993         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7994         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7995         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7996         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7997         case Q3WAVEFUNC_TRIANGLE:
7998                 index *= 4;
7999                 f = index - floor(index);
8000                 if (index < 1)
8001                 {
8002                         // f = f;
8003                 }
8004                 else if (index < 2)
8005                         f = 1 - f;
8006                 else if (index < 3)
8007                         f = -f;
8008                 else
8009                         f = -(1 - f);
8010                 break;
8011         }
8012         f = parms[0] + parms[1] * f;
8013         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
8014                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
8015         return (float) f;
8016 }
8017
8018 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
8019 {
8020         int w, h, idx;
8021         float shadertime;
8022         float f;
8023         float offsetd[2];
8024         float tcmat[12];
8025         matrix4x4_t matrix, temp;
8026         // if shadertime exceeds about 9 hours (32768 seconds), just wrap it,
8027         // it's better to have one huge fixup every 9 hours than gradual
8028         // degradation over time which looks consistently bad after many hours.
8029         //
8030         // tcmod scroll in particular suffers from this degradation which can't be
8031         // effectively worked around even with floor() tricks because we don't
8032         // know if tcmod scroll is the last tcmod being applied, and for clampmap
8033         // a workaround involving floor() would be incorrect anyway...
8034         shadertime = rsurface.shadertime;
8035         if (shadertime >= 32768.0f)
8036                 shadertime -= floor(rsurface.shadertime * (1.0f / 32768.0f)) * 32768.0f;
8037         switch(tcmod->tcmod)
8038         {
8039                 case Q3TCMOD_COUNT:
8040                 case Q3TCMOD_NONE:
8041                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8042                                 matrix = r_waterscrollmatrix;
8043                         else
8044                                 matrix = identitymatrix;
8045                         break;
8046                 case Q3TCMOD_ENTITYTRANSLATE:
8047                         // this is used in Q3 to allow the gamecode to control texcoord
8048                         // scrolling on the entity, which is not supported in darkplaces yet.
8049                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
8050                         break;
8051                 case Q3TCMOD_ROTATE:
8052                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
8053                         Matrix4x4_ConcatRotate(&matrix, tcmod->parms[0] * rsurface.shadertime, 0, 0, 1);
8054                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
8055                         break;
8056                 case Q3TCMOD_SCALE:
8057                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
8058                         break;
8059                 case Q3TCMOD_SCROLL:
8060                         // this particular tcmod is a "bug for bug" compatible one with regards to
8061                         // Quake3, the wrapping is unnecessary with our shadetime fix but quake3
8062                         // specifically did the wrapping and so we must mimic that...
8063                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
8064                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
8065                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
8066                         break;
8067                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
8068                         w = (int) tcmod->parms[0];
8069                         h = (int) tcmod->parms[1];
8070                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
8071                         f = f - floor(f);
8072                         idx = (int) floor(f * w * h);
8073                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
8074                         break;
8075                 case Q3TCMOD_STRETCH:
8076                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
8077                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
8078                         break;
8079                 case Q3TCMOD_TRANSFORM:
8080                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
8081                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
8082                         VectorSet(tcmat +  6, 0                   , 0                , 1);
8083                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
8084                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
8085                         break;
8086                 case Q3TCMOD_TURBULENT:
8087                         // this is handled in the RSurf_PrepareVertices function
8088                         matrix = identitymatrix;
8089                         break;
8090         }
8091         temp = *texmatrix;
8092         Matrix4x4_Concat(texmatrix, &matrix, &temp);
8093 }
8094
8095 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
8096 {
8097         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
8098         char name[MAX_QPATH];
8099         skinframe_t *skinframe;
8100         unsigned char pixels[296*194];
8101         strlcpy(cache->name, skinname, sizeof(cache->name));
8102         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
8103         if (developer_loading.integer)
8104                 Con_Printf("loading %s\n", name);
8105         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
8106         if (!skinframe || !skinframe->base)
8107         {
8108                 unsigned char *f;
8109                 fs_offset_t filesize;
8110                 skinframe = NULL;
8111                 f = FS_LoadFile(name, tempmempool, true, &filesize);
8112                 if (f)
8113                 {
8114                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
8115                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
8116                         Mem_Free(f);
8117                 }
8118         }
8119         cache->skinframe = skinframe;
8120 }
8121
8122 texture_t *R_GetCurrentTexture(texture_t *t)
8123 {
8124         int i;
8125         const entity_render_t *ent = rsurface.entity;
8126         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
8127         q3shaderinfo_layer_tcmod_t *tcmod;
8128
8129         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
8130                 return t->currentframe;
8131         t->update_lastrenderframe = r_textureframe;
8132         t->update_lastrenderentity = (void *)ent;
8133
8134         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
8135                 t->camera_entity = ent->entitynumber;
8136         else
8137                 t->camera_entity = 0;
8138
8139         // switch to an alternate material if this is a q1bsp animated material
8140         {
8141                 texture_t *texture = t;
8142                 int s = rsurface.ent_skinnum;
8143                 if ((unsigned int)s >= (unsigned int)model->numskins)
8144                         s = 0;
8145                 if (model->skinscenes)
8146                 {
8147                         if (model->skinscenes[s].framecount > 1)
8148                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
8149                         else
8150                                 s = model->skinscenes[s].firstframe;
8151                 }
8152                 if (s > 0)
8153                         t = t + s * model->num_surfaces;
8154                 if (t->animated)
8155                 {
8156                         // use an alternate animation if the entity's frame is not 0,
8157                         // and only if the texture has an alternate animation
8158                         if (t->animated == 2) // q2bsp
8159                                 t = t->anim_frames[0][ent->framegroupblend[0].frame % t->anim_total[0]];
8160                         else if (rsurface.ent_alttextures && t->anim_total[1])
8161                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
8162                         else
8163                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
8164                 }
8165                 texture->currentframe = t;
8166         }
8167
8168         // update currentskinframe to be a qw skin or animation frame
8169         if (rsurface.ent_qwskin >= 0)
8170         {
8171                 i = rsurface.ent_qwskin;
8172                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
8173                 {
8174                         r_qwskincache_size = cl.maxclients;
8175                         if (r_qwskincache)
8176                                 Mem_Free(r_qwskincache);
8177                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
8178                 }
8179                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
8180                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
8181                 t->currentskinframe = r_qwskincache[i].skinframe;
8182                 if (t->currentskinframe == NULL)
8183                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8184         }
8185         else if (t->numskinframes >= 2)
8186                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
8187         if (t->backgroundnumskinframes >= 2)
8188                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
8189
8190         t->currentmaterialflags = t->basematerialflags;
8191         t->currentalpha = rsurface.colormod[3] * t->basealpha;
8192         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
8193                 t->currentalpha *= r_wateralpha.value;
8194         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
8195                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
8196         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
8197                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
8198         if (!(rsurface.ent_flags & RENDER_LIGHT))
8199                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
8200         else if (FAKELIGHT_ENABLED)
8201         {
8202                 // no modellight if using fakelight for the map
8203         }
8204         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
8205         {
8206                 // pick a model lighting mode
8207                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
8208                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
8209                 else
8210                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
8211         }
8212         if (rsurface.ent_flags & RENDER_ADDITIVE)
8213                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8214         else if (t->currentalpha < 1)
8215                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8216         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8217         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8218                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8219         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8220                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8221         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8222                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8223         if (t->backgroundnumskinframes)
8224                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8225         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8226         {
8227                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8228                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8229         }
8230         else
8231                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8232         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8233         {
8234                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8235                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8236         }
8237         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8238                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8239
8240         // there is no tcmod
8241         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8242         {
8243                 t->currenttexmatrix = r_waterscrollmatrix;
8244                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8245         }
8246         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8247         {
8248                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8249                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8250         }
8251
8252         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8253                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8254         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8255                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8256
8257         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8258         if (t->currentskinframe->qpixels)
8259                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8260         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8261         if (!t->basetexture)
8262                 t->basetexture = r_texture_notexture;
8263         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8264         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8265         t->nmaptexture = t->currentskinframe->nmap;
8266         if (!t->nmaptexture)
8267                 t->nmaptexture = r_texture_blanknormalmap;
8268         t->glosstexture = r_texture_black;
8269         t->glowtexture = t->currentskinframe->glow;
8270         t->fogtexture = t->currentskinframe->fog;
8271         t->reflectmasktexture = t->currentskinframe->reflect;
8272         if (t->backgroundnumskinframes)
8273         {
8274                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8275                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8276                 t->backgroundglosstexture = r_texture_black;
8277                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8278                 if (!t->backgroundnmaptexture)
8279                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8280                 // make sure that if glow is going to be used, both textures are not NULL
8281                 if (!t->backgroundglowtexture && t->glowtexture)
8282                         t->backgroundglowtexture = r_texture_black;
8283                 if (!t->glowtexture && t->backgroundglowtexture)
8284                         t->glowtexture = r_texture_black;
8285         }
8286         else
8287         {
8288                 t->backgroundbasetexture = r_texture_white;
8289                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8290                 t->backgroundglosstexture = r_texture_black;
8291                 t->backgroundglowtexture = NULL;
8292         }
8293         t->specularpower = r_shadow_glossexponent.value;
8294         // TODO: store reference values for these in the texture?
8295         t->specularscale = 0;
8296         if (r_shadow_gloss.integer > 0)
8297         {
8298                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8299                 {
8300                         if (r_shadow_glossintensity.value > 0)
8301                         {
8302                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8303                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8304                                 t->specularscale = r_shadow_glossintensity.value;
8305                         }
8306                 }
8307                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8308                 {
8309                         t->glosstexture = r_texture_white;
8310                         t->backgroundglosstexture = r_texture_white;
8311                         t->specularscale = r_shadow_gloss2intensity.value;
8312                         t->specularpower = r_shadow_gloss2exponent.value;
8313                 }
8314         }
8315         t->specularscale *= t->specularscalemod;
8316         t->specularpower *= t->specularpowermod;
8317         t->rtlightambient = 0;
8318
8319         // lightmaps mode looks bad with dlights using actual texturing, so turn
8320         // off the colormap and glossmap, but leave the normalmap on as it still
8321         // accurately represents the shading involved
8322         if (gl_lightmaps.integer)
8323         {
8324                 t->basetexture = r_texture_grey128;
8325                 t->pantstexture = r_texture_black;
8326                 t->shirttexture = r_texture_black;
8327                 if (gl_lightmaps.integer < 2)
8328                         t->nmaptexture = r_texture_blanknormalmap;
8329                 t->glosstexture = r_texture_black;
8330                 t->glowtexture = NULL;
8331                 t->fogtexture = NULL;
8332                 t->reflectmasktexture = NULL;
8333                 t->backgroundbasetexture = NULL;
8334                 if (gl_lightmaps.integer < 2)
8335                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8336                 t->backgroundglosstexture = r_texture_black;
8337                 t->backgroundglowtexture = NULL;
8338                 t->specularscale = 0;
8339                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8340         }
8341
8342         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8343         VectorClear(t->dlightcolor);
8344         t->currentnumlayers = 0;
8345         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8346         {
8347                 int blendfunc1, blendfunc2;
8348                 qboolean depthmask;
8349                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8350                 {
8351                         blendfunc1 = GL_SRC_ALPHA;
8352                         blendfunc2 = GL_ONE;
8353                 }
8354                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8355                 {
8356                         blendfunc1 = GL_SRC_ALPHA;
8357                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8358                 }
8359                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8360                 {
8361                         blendfunc1 = t->customblendfunc[0];
8362                         blendfunc2 = t->customblendfunc[1];
8363                 }
8364                 else
8365                 {
8366                         blendfunc1 = GL_ONE;
8367                         blendfunc2 = GL_ZERO;
8368                 }
8369                 // don't colormod evilblend textures
8370                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8371                         VectorSet(t->lightmapcolor, 1, 1, 1);
8372                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8373                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8374                 {
8375                         // fullbright is not affected by r_refdef.lightmapintensity
8376                         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]);
8377                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8378                                 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]);
8379                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8380                                 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]);
8381                 }
8382                 else
8383                 {
8384                         vec3_t ambientcolor;
8385                         float colorscale;
8386                         // set the color tint used for lights affecting this surface
8387                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8388                         colorscale = 2;
8389                         // q3bsp has no lightmap updates, so the lightstylevalue that
8390                         // would normally be baked into the lightmap must be
8391                         // applied to the color
8392                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8393                         if (model->type == mod_brushq3)
8394                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8395                         colorscale *= r_refdef.lightmapintensity;
8396                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8397                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8398                         // basic lit geometry
8399                         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]);
8400                         // add pants/shirt if needed
8401                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8402                                 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]);
8403                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8404                                 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]);
8405                         // now add ambient passes if needed
8406                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8407                         {
8408                                 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]);
8409                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8410                                         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]);
8411                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8412                                         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]);
8413                         }
8414                 }
8415                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8416                         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]);
8417                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8418                 {
8419                         // if this is opaque use alpha blend which will darken the earlier
8420                         // passes cheaply.
8421                         //
8422                         // if this is an alpha blended material, all the earlier passes
8423                         // were darkened by fog already, so we only need to add the fog
8424                         // color ontop through the fog mask texture
8425                         //
8426                         // if this is an additive blended material, all the earlier passes
8427                         // were darkened by fog already, and we should not add fog color
8428                         // (because the background was not darkened, there is no fog color
8429                         // that was lost behind it).
8430                         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]);
8431                 }
8432         }
8433
8434         return t->currentframe;
8435 }
8436
8437 rsurfacestate_t rsurface;
8438
8439 void RSurf_ActiveWorldEntity(void)
8440 {
8441         dp_model_t *model = r_refdef.scene.worldmodel;
8442         //if (rsurface.entity == r_refdef.scene.worldentity)
8443         //      return;
8444         rsurface.entity = r_refdef.scene.worldentity;
8445         rsurface.skeleton = NULL;
8446         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8447         rsurface.ent_skinnum = 0;
8448         rsurface.ent_qwskin = -1;
8449         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8450         rsurface.shadertime = r_refdef.scene.time;
8451         rsurface.matrix = identitymatrix;
8452         rsurface.inversematrix = identitymatrix;
8453         rsurface.matrixscale = 1;
8454         rsurface.inversematrixscale = 1;
8455         R_EntityMatrix(&identitymatrix);
8456         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8457         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8458         rsurface.fograngerecip = r_refdef.fograngerecip;
8459         rsurface.fogheightfade = r_refdef.fogheightfade;
8460         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8461         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8462         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8463         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8464         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8465         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8466         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8467         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8468         rsurface.colormod[3] = 1;
8469         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);
8470         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8471         rsurface.frameblend[0].lerp = 1;
8472         rsurface.ent_alttextures = false;
8473         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8474         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8475         rsurface.entityskeletaltransform3x4 = NULL;
8476         rsurface.entityskeletaltransform3x4buffer = NULL;
8477         rsurface.entityskeletaltransform3x4offset = 0;
8478         rsurface.entityskeletaltransform3x4size = 0;;
8479         rsurface.entityskeletalnumtransforms = 0;
8480         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8481         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8482         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8483         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8484         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8485         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8486         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8487         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8488         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8489         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8490         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8491         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8492         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8493         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8494         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8495         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8496         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8497         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8498         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8499         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8500         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8501         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8502         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8503         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8504         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8505         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8506         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8507         rsurface.modelelement3i = model->surfmesh.data_element3i;
8508         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8509         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8510         rsurface.modelelement3s = model->surfmesh.data_element3s;
8511         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8512         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8513         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8514         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8515         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8516         rsurface.modelsurfaces = model->data_surfaces;
8517         rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8518         rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8519         rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8520         rsurface.modelgeneratedvertex = false;
8521         rsurface.batchgeneratedvertex = false;
8522         rsurface.batchfirstvertex = 0;
8523         rsurface.batchnumvertices = 0;
8524         rsurface.batchfirsttriangle = 0;
8525         rsurface.batchnumtriangles = 0;
8526         rsurface.batchvertex3f  = NULL;
8527         rsurface.batchvertex3f_vertexbuffer = NULL;
8528         rsurface.batchvertex3f_bufferoffset = 0;
8529         rsurface.batchsvector3f = NULL;
8530         rsurface.batchsvector3f_vertexbuffer = NULL;
8531         rsurface.batchsvector3f_bufferoffset = 0;
8532         rsurface.batchtvector3f = NULL;
8533         rsurface.batchtvector3f_vertexbuffer = NULL;
8534         rsurface.batchtvector3f_bufferoffset = 0;
8535         rsurface.batchnormal3f  = NULL;
8536         rsurface.batchnormal3f_vertexbuffer = NULL;
8537         rsurface.batchnormal3f_bufferoffset = 0;
8538         rsurface.batchlightmapcolor4f = NULL;
8539         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8540         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8541         rsurface.batchtexcoordtexture2f = NULL;
8542         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8543         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8544         rsurface.batchtexcoordlightmap2f = NULL;
8545         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8546         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8547         rsurface.batchskeletalindex4ub = NULL;
8548         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8549         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8550         rsurface.batchskeletalweight4ub = NULL;
8551         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8552         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8553         rsurface.batchvertexmesh = NULL;
8554         rsurface.batchvertexmesh_vertexbuffer = NULL;
8555         rsurface.batchvertexmesh_bufferoffset = 0;
8556         rsurface.batchelement3i = NULL;
8557         rsurface.batchelement3i_indexbuffer = NULL;
8558         rsurface.batchelement3i_bufferoffset = 0;
8559         rsurface.batchelement3s = NULL;
8560         rsurface.batchelement3s_indexbuffer = NULL;
8561         rsurface.batchelement3s_bufferoffset = 0;
8562         rsurface.passcolor4f = NULL;
8563         rsurface.passcolor4f_vertexbuffer = NULL;
8564         rsurface.passcolor4f_bufferoffset = 0;
8565         rsurface.forcecurrenttextureupdate = false;
8566 }
8567
8568 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8569 {
8570         dp_model_t *model = ent->model;
8571         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8572         //      return;
8573         rsurface.entity = (entity_render_t *)ent;
8574         rsurface.skeleton = ent->skeleton;
8575         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8576         rsurface.ent_skinnum = ent->skinnum;
8577         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;
8578         rsurface.ent_flags = ent->flags;
8579         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8580         rsurface.matrix = ent->matrix;
8581         rsurface.inversematrix = ent->inversematrix;
8582         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8583         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8584         R_EntityMatrix(&rsurface.matrix);
8585         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8586         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8587         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8588         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8589         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8590         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8591         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8592         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8593         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8594         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8595         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8596         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8597         rsurface.colormod[3] = ent->alpha;
8598         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8599         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8600         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8601         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8602         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8603         if (ent->model->brush.submodel && !prepass)
8604         {
8605                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8606                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8607         }
8608         // if the animcache code decided it should use the shader path, skip the deform step
8609         rsurface.entityskeletaltransform3x4 = ent->animcache_skeletaltransform3x4;
8610         rsurface.entityskeletaltransform3x4buffer = ent->animcache_skeletaltransform3x4buffer;
8611         rsurface.entityskeletaltransform3x4offset = ent->animcache_skeletaltransform3x4offset;
8612         rsurface.entityskeletaltransform3x4size = ent->animcache_skeletaltransform3x4size;
8613         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8614         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8615         {
8616                 if (ent->animcache_vertex3f)
8617                 {
8618                         r_refdef.stats[r_stat_batch_entitycache_count]++;
8619                         r_refdef.stats[r_stat_batch_entitycache_surfaces] += model->num_surfaces;
8620                         r_refdef.stats[r_stat_batch_entitycache_vertices] += model->surfmesh.num_vertices;
8621                         r_refdef.stats[r_stat_batch_entitycache_triangles] += model->surfmesh.num_triangles;
8622                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8623                         rsurface.modelvertex3f_vertexbuffer = ent->animcache_vertex3f_vertexbuffer;
8624                         rsurface.modelvertex3f_bufferoffset = ent->animcache_vertex3f_bufferoffset;
8625                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8626                         rsurface.modelsvector3f_vertexbuffer = wanttangents ? ent->animcache_svector3f_vertexbuffer : NULL;
8627                         rsurface.modelsvector3f_bufferoffset = wanttangents ? ent->animcache_svector3f_bufferoffset : 0;
8628                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8629                         rsurface.modeltvector3f_vertexbuffer = wanttangents ? ent->animcache_tvector3f_vertexbuffer : NULL;
8630                         rsurface.modeltvector3f_bufferoffset = wanttangents ? ent->animcache_tvector3f_bufferoffset : 0;
8631                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8632                         rsurface.modelnormal3f_vertexbuffer = wantnormals ? ent->animcache_normal3f_vertexbuffer : NULL;
8633                         rsurface.modelnormal3f_bufferoffset = wantnormals ? ent->animcache_normal3f_bufferoffset : 0;
8634                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8635                         rsurface.modelvertexmesh_vertexbuffer = ent->animcache_vertexmesh_vertexbuffer;
8636                         rsurface.modelvertexmesh_bufferoffset = ent->animcache_vertexmesh_bufferoffset;
8637                 }
8638                 else if (wanttangents)
8639                 {
8640                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8641                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8642                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8643                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8644                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8645                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8646                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8647                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8648                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8649                         rsurface.modelvertexmesh = NULL;
8650                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8651                         rsurface.modelvertexmesh_bufferoffset = 0;
8652                         rsurface.modelvertex3f_vertexbuffer = NULL;
8653                         rsurface.modelvertex3f_bufferoffset = 0;
8654                         rsurface.modelvertex3f_vertexbuffer = 0;
8655                         rsurface.modelvertex3f_bufferoffset = 0;
8656                         rsurface.modelsvector3f_vertexbuffer = 0;
8657                         rsurface.modelsvector3f_bufferoffset = 0;
8658                         rsurface.modeltvector3f_vertexbuffer = 0;
8659                         rsurface.modeltvector3f_bufferoffset = 0;
8660                         rsurface.modelnormal3f_vertexbuffer = 0;
8661                         rsurface.modelnormal3f_bufferoffset = 0;
8662                 }
8663                 else if (wantnormals)
8664                 {
8665                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8666                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8667                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8668                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8669                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8670                         rsurface.modelsvector3f = NULL;
8671                         rsurface.modeltvector3f = NULL;
8672                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8673                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8674                         rsurface.modelvertexmesh = NULL;
8675                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8676                         rsurface.modelvertexmesh_bufferoffset = 0;
8677                         rsurface.modelvertex3f_vertexbuffer = NULL;
8678                         rsurface.modelvertex3f_bufferoffset = 0;
8679                         rsurface.modelvertex3f_vertexbuffer = 0;
8680                         rsurface.modelvertex3f_bufferoffset = 0;
8681                         rsurface.modelsvector3f_vertexbuffer = 0;
8682                         rsurface.modelsvector3f_bufferoffset = 0;
8683                         rsurface.modeltvector3f_vertexbuffer = 0;
8684                         rsurface.modeltvector3f_bufferoffset = 0;
8685                         rsurface.modelnormal3f_vertexbuffer = 0;
8686                         rsurface.modelnormal3f_bufferoffset = 0;
8687                 }
8688                 else
8689                 {
8690                         r_refdef.stats[r_stat_batch_entityanimate_count]++;
8691                         r_refdef.stats[r_stat_batch_entityanimate_surfaces] += model->num_surfaces;
8692                         r_refdef.stats[r_stat_batch_entityanimate_vertices] += model->surfmesh.num_vertices;
8693                         r_refdef.stats[r_stat_batch_entityanimate_triangles] += model->surfmesh.num_triangles;
8694                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8695                         rsurface.modelsvector3f = NULL;
8696                         rsurface.modeltvector3f = NULL;
8697                         rsurface.modelnormal3f = NULL;
8698                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8699                         rsurface.modelvertexmesh = NULL;
8700                         rsurface.modelvertexmesh_vertexbuffer = NULL;
8701                         rsurface.modelvertexmesh_bufferoffset = 0;
8702                         rsurface.modelvertex3f_vertexbuffer = NULL;
8703                         rsurface.modelvertex3f_bufferoffset = 0;
8704                         rsurface.modelvertex3f_vertexbuffer = 0;
8705                         rsurface.modelvertex3f_bufferoffset = 0;
8706                         rsurface.modelsvector3f_vertexbuffer = 0;
8707                         rsurface.modelsvector3f_bufferoffset = 0;
8708                         rsurface.modeltvector3f_vertexbuffer = 0;
8709                         rsurface.modeltvector3f_bufferoffset = 0;
8710                         rsurface.modelnormal3f_vertexbuffer = 0;
8711                         rsurface.modelnormal3f_bufferoffset = 0;
8712                 }
8713                 rsurface.modelgeneratedvertex = true;
8714         }
8715         else
8716         {
8717                 if (rsurface.entityskeletaltransform3x4)
8718                 {
8719                         r_refdef.stats[r_stat_batch_entityskeletal_count]++;
8720                         r_refdef.stats[r_stat_batch_entityskeletal_surfaces] += model->num_surfaces;
8721                         r_refdef.stats[r_stat_batch_entityskeletal_vertices] += model->surfmesh.num_vertices;
8722                         r_refdef.stats[r_stat_batch_entityskeletal_triangles] += model->surfmesh.num_triangles;
8723                 }
8724                 else
8725                 {
8726                         r_refdef.stats[r_stat_batch_entitystatic_count]++;
8727                         r_refdef.stats[r_stat_batch_entitystatic_surfaces] += model->num_surfaces;
8728                         r_refdef.stats[r_stat_batch_entitystatic_vertices] += model->surfmesh.num_vertices;
8729                         r_refdef.stats[r_stat_batch_entitystatic_triangles] += model->surfmesh.num_triangles;
8730                 }
8731                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8732                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8733                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8734                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8735                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8736                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8737                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8738                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8739                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8740                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8741                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8742                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8743                 rsurface.modelvertexmesh = model->surfmesh.data_vertexmesh;
8744                 rsurface.modelvertexmesh_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8745                 rsurface.modelvertexmesh_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8746                 rsurface.modelgeneratedvertex = false;
8747         }
8748         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8749         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8750         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8751         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8752         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8753         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8754         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8755         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8756         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8757         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8758         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8759         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8760         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8761         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8762         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8763         rsurface.modelelement3i = model->surfmesh.data_element3i;
8764         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8765         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8766         rsurface.modelelement3s = model->surfmesh.data_element3s;
8767         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8768         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8769         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8770         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8771         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8772         rsurface.modelsurfaces = model->data_surfaces;
8773         rsurface.batchgeneratedvertex = false;
8774         rsurface.batchfirstvertex = 0;
8775         rsurface.batchnumvertices = 0;
8776         rsurface.batchfirsttriangle = 0;
8777         rsurface.batchnumtriangles = 0;
8778         rsurface.batchvertex3f  = NULL;
8779         rsurface.batchvertex3f_vertexbuffer = NULL;
8780         rsurface.batchvertex3f_bufferoffset = 0;
8781         rsurface.batchsvector3f = NULL;
8782         rsurface.batchsvector3f_vertexbuffer = NULL;
8783         rsurface.batchsvector3f_bufferoffset = 0;
8784         rsurface.batchtvector3f = NULL;
8785         rsurface.batchtvector3f_vertexbuffer = NULL;
8786         rsurface.batchtvector3f_bufferoffset = 0;
8787         rsurface.batchnormal3f  = NULL;
8788         rsurface.batchnormal3f_vertexbuffer = NULL;
8789         rsurface.batchnormal3f_bufferoffset = 0;
8790         rsurface.batchlightmapcolor4f = NULL;
8791         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8792         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8793         rsurface.batchtexcoordtexture2f = NULL;
8794         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8795         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8796         rsurface.batchtexcoordlightmap2f = NULL;
8797         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8798         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8799         rsurface.batchskeletalindex4ub = NULL;
8800         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8801         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8802         rsurface.batchskeletalweight4ub = NULL;
8803         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8804         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8805         rsurface.batchvertexmesh = NULL;
8806         rsurface.batchvertexmesh_vertexbuffer = NULL;
8807         rsurface.batchvertexmesh_bufferoffset = 0;
8808         rsurface.batchelement3i = NULL;
8809         rsurface.batchelement3i_indexbuffer = NULL;
8810         rsurface.batchelement3i_bufferoffset = 0;
8811         rsurface.batchelement3s = NULL;
8812         rsurface.batchelement3s_indexbuffer = NULL;
8813         rsurface.batchelement3s_bufferoffset = 0;
8814         rsurface.passcolor4f = NULL;
8815         rsurface.passcolor4f_vertexbuffer = NULL;
8816         rsurface.passcolor4f_bufferoffset = 0;
8817         rsurface.forcecurrenttextureupdate = false;
8818 }
8819
8820 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)
8821 {
8822         rsurface.entity = r_refdef.scene.worldentity;
8823         rsurface.skeleton = NULL;
8824         rsurface.ent_skinnum = 0;
8825         rsurface.ent_qwskin = -1;
8826         rsurface.ent_flags = entflags;
8827         rsurface.shadertime = r_refdef.scene.time - shadertime;
8828         rsurface.modelnumvertices = numvertices;
8829         rsurface.modelnumtriangles = numtriangles;
8830         rsurface.matrix = *matrix;
8831         rsurface.inversematrix = *inversematrix;
8832         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8833         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8834         R_EntityMatrix(&rsurface.matrix);
8835         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8836         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8837         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8838         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8839         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8840         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8841         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8842         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8843         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8844         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8845         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8846         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8847         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);
8848         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8849         rsurface.frameblend[0].lerp = 1;
8850         rsurface.ent_alttextures = false;
8851         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8852         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8853         rsurface.entityskeletaltransform3x4 = NULL;
8854         rsurface.entityskeletaltransform3x4buffer = NULL;
8855         rsurface.entityskeletaltransform3x4offset = 0;
8856         rsurface.entityskeletaltransform3x4size = 0;
8857         rsurface.entityskeletalnumtransforms = 0;
8858         r_refdef.stats[r_stat_batch_entitycustom_count]++;
8859         r_refdef.stats[r_stat_batch_entitycustom_surfaces] += 1;
8860         r_refdef.stats[r_stat_batch_entitycustom_vertices] += rsurface.modelnumvertices;
8861         r_refdef.stats[r_stat_batch_entitycustom_triangles] += rsurface.modelnumtriangles;
8862         if (wanttangents)
8863         {
8864                 rsurface.modelvertex3f = (float *)vertex3f;
8865                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8866                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8867                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8868         }
8869         else if (wantnormals)
8870         {
8871                 rsurface.modelvertex3f = (float *)vertex3f;
8872                 rsurface.modelsvector3f = NULL;
8873                 rsurface.modeltvector3f = NULL;
8874                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8875         }
8876         else
8877         {
8878                 rsurface.modelvertex3f = (float *)vertex3f;
8879                 rsurface.modelsvector3f = NULL;
8880                 rsurface.modeltvector3f = NULL;
8881                 rsurface.modelnormal3f = NULL;
8882         }
8883         rsurface.modelvertexmesh = NULL;
8884         rsurface.modelvertexmesh_vertexbuffer = NULL;
8885         rsurface.modelvertexmesh_bufferoffset = 0;
8886         rsurface.modelvertex3f_vertexbuffer = 0;
8887         rsurface.modelvertex3f_bufferoffset = 0;
8888         rsurface.modelsvector3f_vertexbuffer = 0;
8889         rsurface.modelsvector3f_bufferoffset = 0;
8890         rsurface.modeltvector3f_vertexbuffer = 0;
8891         rsurface.modeltvector3f_bufferoffset = 0;
8892         rsurface.modelnormal3f_vertexbuffer = 0;
8893         rsurface.modelnormal3f_bufferoffset = 0;
8894         rsurface.modelgeneratedvertex = true;
8895         rsurface.modellightmapcolor4f  = (float *)color4f;
8896         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8897         rsurface.modellightmapcolor4f_bufferoffset = 0;
8898         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8899         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8900         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8901         rsurface.modeltexcoordlightmap2f  = NULL;
8902         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8903         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8904         rsurface.modelskeletalindex4ub = NULL;
8905         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8906         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8907         rsurface.modelskeletalweight4ub = NULL;
8908         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8909         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8910         rsurface.modelelement3i = (int *)element3i;
8911         rsurface.modelelement3i_indexbuffer = NULL;
8912         rsurface.modelelement3i_bufferoffset = 0;
8913         rsurface.modelelement3s = (unsigned short *)element3s;
8914         rsurface.modelelement3s_indexbuffer = NULL;
8915         rsurface.modelelement3s_bufferoffset = 0;
8916         rsurface.modellightmapoffsets = NULL;
8917         rsurface.modelsurfaces = NULL;
8918         rsurface.batchgeneratedvertex = false;
8919         rsurface.batchfirstvertex = 0;
8920         rsurface.batchnumvertices = 0;
8921         rsurface.batchfirsttriangle = 0;
8922         rsurface.batchnumtriangles = 0;
8923         rsurface.batchvertex3f  = NULL;
8924         rsurface.batchvertex3f_vertexbuffer = NULL;
8925         rsurface.batchvertex3f_bufferoffset = 0;
8926         rsurface.batchsvector3f = NULL;
8927         rsurface.batchsvector3f_vertexbuffer = NULL;
8928         rsurface.batchsvector3f_bufferoffset = 0;
8929         rsurface.batchtvector3f = NULL;
8930         rsurface.batchtvector3f_vertexbuffer = NULL;
8931         rsurface.batchtvector3f_bufferoffset = 0;
8932         rsurface.batchnormal3f  = NULL;
8933         rsurface.batchnormal3f_vertexbuffer = NULL;
8934         rsurface.batchnormal3f_bufferoffset = 0;
8935         rsurface.batchlightmapcolor4f = NULL;
8936         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8937         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8938         rsurface.batchtexcoordtexture2f = NULL;
8939         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8940         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8941         rsurface.batchtexcoordlightmap2f = NULL;
8942         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8943         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8944         rsurface.batchskeletalindex4ub = NULL;
8945         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8946         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8947         rsurface.batchskeletalweight4ub = NULL;
8948         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8949         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8950         rsurface.batchvertexmesh = NULL;
8951         rsurface.batchvertexmesh_vertexbuffer = NULL;
8952         rsurface.batchvertexmesh_bufferoffset = 0;
8953         rsurface.batchelement3i = NULL;
8954         rsurface.batchelement3i_indexbuffer = NULL;
8955         rsurface.batchelement3i_bufferoffset = 0;
8956         rsurface.batchelement3s = NULL;
8957         rsurface.batchelement3s_indexbuffer = NULL;
8958         rsurface.batchelement3s_bufferoffset = 0;
8959         rsurface.passcolor4f = NULL;
8960         rsurface.passcolor4f_vertexbuffer = NULL;
8961         rsurface.passcolor4f_bufferoffset = 0;
8962         rsurface.forcecurrenttextureupdate = true;
8963
8964         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8965         {
8966                 if ((wantnormals || wanttangents) && !normal3f)
8967                 {
8968                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8969                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8970                 }
8971                 if (wanttangents && !svector3f)
8972                 {
8973                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8974                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8975                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8976                 }
8977         }
8978 }
8979
8980 float RSurf_FogPoint(const float *v)
8981 {
8982         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8983         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8984         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8985         float FogHeightFade = r_refdef.fogheightfade;
8986         float fogfrac;
8987         unsigned int fogmasktableindex;
8988         if (r_refdef.fogplaneviewabove)
8989                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8990         else
8991                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8992         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8993         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8994 }
8995
8996 float RSurf_FogVertex(const float *v)
8997 {
8998         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8999         float FogPlaneViewDist = rsurface.fogplaneviewdist;
9000         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
9001         float FogHeightFade = rsurface.fogheightfade;
9002         float fogfrac;
9003         unsigned int fogmasktableindex;
9004         if (r_refdef.fogplaneviewabove)
9005                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
9006         else
9007                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
9008         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
9009         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
9010 }
9011
9012 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
9013 {
9014         int i;
9015         for (i = 0;i < numelements;i++)
9016                 outelement3i[i] = inelement3i[i] + adjust;
9017 }
9018
9019 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
9020 extern cvar_t gl_vbo;
9021 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
9022 {
9023         int deformindex;
9024         int firsttriangle;
9025         int numtriangles;
9026         int firstvertex;
9027         int endvertex;
9028         int numvertices;
9029         int surfacefirsttriangle;
9030         int surfacenumtriangles;
9031         int surfacefirstvertex;
9032         int surfaceendvertex;
9033         int surfacenumvertices;
9034         int batchnumsurfaces = texturenumsurfaces;
9035         int batchnumvertices;
9036         int batchnumtriangles;
9037         int needsupdate;
9038         int i, j;
9039         qboolean gaps;
9040         qboolean dynamicvertex;
9041         float amplitude;
9042         float animpos;
9043         float scale;
9044         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
9045         float waveparms[4];
9046         unsigned char *ub;
9047         q3shaderinfo_deform_t *deform;
9048         const msurface_t *surface, *firstsurface;
9049         r_vertexmesh_t *vertexmesh;
9050         if (!texturenumsurfaces)
9051                 return;
9052         // find vertex range of this surface batch
9053         gaps = false;
9054         firstsurface = texturesurfacelist[0];
9055         firsttriangle = firstsurface->num_firsttriangle;
9056         batchnumvertices = 0;
9057         batchnumtriangles = 0;
9058         firstvertex = endvertex = firstsurface->num_firstvertex;
9059         for (i = 0;i < texturenumsurfaces;i++)
9060         {
9061                 surface = texturesurfacelist[i];
9062                 if (surface != firstsurface + i)
9063                         gaps = true;
9064                 surfacefirstvertex = surface->num_firstvertex;
9065                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
9066                 surfacenumvertices = surface->num_vertices;
9067                 surfacenumtriangles = surface->num_triangles;
9068                 if (firstvertex > surfacefirstvertex)
9069                         firstvertex = surfacefirstvertex;
9070                 if (endvertex < surfaceendvertex)
9071                         endvertex = surfaceendvertex;
9072                 batchnumvertices += surfacenumvertices;
9073                 batchnumtriangles += surfacenumtriangles;
9074         }
9075
9076         r_refdef.stats[r_stat_batch_batches]++;
9077         if (gaps)
9078                 r_refdef.stats[r_stat_batch_withgaps]++;
9079         r_refdef.stats[r_stat_batch_surfaces] += batchnumsurfaces;
9080         r_refdef.stats[r_stat_batch_vertices] += batchnumvertices;
9081         r_refdef.stats[r_stat_batch_triangles] += batchnumtriangles;
9082
9083         // we now know the vertex range used, and if there are any gaps in it
9084         rsurface.batchfirstvertex = firstvertex;
9085         rsurface.batchnumvertices = endvertex - firstvertex;
9086         rsurface.batchfirsttriangle = firsttriangle;
9087         rsurface.batchnumtriangles = batchnumtriangles;
9088
9089         // this variable holds flags for which properties have been updated that
9090         // may require regenerating vertexmesh array...
9091         needsupdate = 0;
9092
9093         // check if any dynamic vertex processing must occur
9094         dynamicvertex = false;
9095
9096         // a cvar to force the dynamic vertex path to be taken, for debugging
9097         if (r_batch_debugdynamicvertexpath.integer)
9098         {
9099                 if (!dynamicvertex)
9100                 {
9101                         r_refdef.stats[r_stat_batch_dynamic_batches_because_cvar] += 1;
9102                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_cvar] += batchnumsurfaces;
9103                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_cvar] += batchnumvertices;
9104                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_cvar] += batchnumtriangles;
9105                 }
9106                 dynamicvertex = true;
9107         }
9108
9109         // if there is a chance of animated vertex colors, it's a dynamic batch
9110         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9111         {
9112                 if (!dynamicvertex)
9113                 {
9114                         r_refdef.stats[r_stat_batch_dynamic_batches_because_lightmapvertex] += 1;
9115                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_lightmapvertex] += batchnumsurfaces;
9116                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_lightmapvertex] += batchnumvertices;
9117                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_lightmapvertex] += batchnumtriangles;
9118                 }
9119                 dynamicvertex = true;
9120                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
9121         }
9122
9123         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9124         {
9125                 switch (deform->deform)
9126                 {
9127                 default:
9128                 case Q3DEFORM_PROJECTIONSHADOW:
9129                 case Q3DEFORM_TEXT0:
9130                 case Q3DEFORM_TEXT1:
9131                 case Q3DEFORM_TEXT2:
9132                 case Q3DEFORM_TEXT3:
9133                 case Q3DEFORM_TEXT4:
9134                 case Q3DEFORM_TEXT5:
9135                 case Q3DEFORM_TEXT6:
9136                 case Q3DEFORM_TEXT7:
9137                 case Q3DEFORM_NONE:
9138                         break;
9139                 case Q3DEFORM_AUTOSPRITE:
9140                         if (!dynamicvertex)
9141                         {
9142                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite] += 1;
9143                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite] += batchnumsurfaces;
9144                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite] += batchnumvertices;
9145                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite] += batchnumtriangles;
9146                         }
9147                         dynamicvertex = true;
9148                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
9149                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9150                         break;
9151                 case Q3DEFORM_AUTOSPRITE2:
9152                         if (!dynamicvertex)
9153                         {
9154                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_autosprite2] += 1;
9155                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_autosprite2] += batchnumsurfaces;
9156                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_autosprite2] += batchnumvertices;
9157                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_autosprite2] += batchnumtriangles;
9158                         }
9159                         dynamicvertex = true;
9160                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9161                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9162                         break;
9163                 case Q3DEFORM_NORMAL:
9164                         if (!dynamicvertex)
9165                         {
9166                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_normal] += 1;
9167                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_normal] += batchnumsurfaces;
9168                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_normal] += batchnumvertices;
9169                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_normal] += batchnumtriangles;
9170                         }
9171                         dynamicvertex = true;
9172                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9173                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9174                         break;
9175                 case Q3DEFORM_WAVE:
9176                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9177                                 break; // if wavefunc is a nop, ignore this transform
9178                         if (!dynamicvertex)
9179                         {
9180                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_wave] += 1;
9181                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_wave] += batchnumsurfaces;
9182                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_wave] += batchnumvertices;
9183                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_wave] += batchnumtriangles;
9184                         }
9185                         dynamicvertex = true;
9186                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9187                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9188                         break;
9189                 case Q3DEFORM_BULGE:
9190                         if (!dynamicvertex)
9191                         {
9192                                 r_refdef.stats[r_stat_batch_dynamic_batches_because_deformvertexes_bulge] += 1;
9193                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_bulge] += batchnumsurfaces;
9194                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_bulge] += batchnumvertices;
9195                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_bulge] += batchnumtriangles;
9196                         }
9197                         dynamicvertex = true;
9198                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
9199                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
9200                         break;
9201                 case Q3DEFORM_MOVE:
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_move] += 1;
9207                                 r_refdef.stats[r_stat_batch_dynamic_surfaces_because_deformvertexes_move] += batchnumsurfaces;
9208                                 r_refdef.stats[r_stat_batch_dynamic_vertices_because_deformvertexes_move] += batchnumvertices;
9209                                 r_refdef.stats[r_stat_batch_dynamic_triangles_because_deformvertexes_move] += batchnumtriangles;
9210                         }
9211                         dynamicvertex = true;
9212                         batchneed |= BATCHNEED_ARRAY_VERTEX;
9213                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
9214                         break;
9215                 }
9216         }
9217         switch(rsurface.texture->tcgen.tcgen)
9218         {
9219         default:
9220         case Q3TCGEN_TEXTURE:
9221                 break;
9222         case Q3TCGEN_LIGHTMAP:
9223                 if (!dynamicvertex)
9224                 {
9225                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_lightmap] += 1;
9226                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_lightmap] += batchnumsurfaces;
9227                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_lightmap] += batchnumvertices;
9228                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_lightmap] += batchnumtriangles;
9229                 }
9230                 dynamicvertex = true;
9231                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9232                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
9233                 break;
9234         case Q3TCGEN_VECTOR:
9235                 if (!dynamicvertex)
9236                 {
9237                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_vector] += 1;
9238                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_vector] += batchnumsurfaces;
9239                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_vector] += batchnumvertices;
9240                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_vector] += batchnumtriangles;
9241                 }
9242                 dynamicvertex = true;
9243                 batchneed |= BATCHNEED_ARRAY_VERTEX;
9244                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9245                 break;
9246         case Q3TCGEN_ENVIRONMENT:
9247                 if (!dynamicvertex)
9248                 {
9249                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcgen_environment] += 1;
9250                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcgen_environment] += batchnumsurfaces;
9251                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcgen_environment] += batchnumvertices;
9252                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcgen_environment] += batchnumtriangles;
9253                 }
9254                 dynamicvertex = true;
9255                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
9256                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9257                 break;
9258         }
9259         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9260         {
9261                 if (!dynamicvertex)
9262                 {
9263                         r_refdef.stats[r_stat_batch_dynamic_batches_because_tcmod_turbulent] += 1;
9264                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_tcmod_turbulent] += batchnumsurfaces;
9265                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_tcmod_turbulent] += batchnumvertices;
9266                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_tcmod_turbulent] += batchnumtriangles;
9267                 }
9268                 dynamicvertex = true;
9269                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
9270                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
9271         }
9272
9273         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9274         {
9275                 if (!dynamicvertex)
9276                 {
9277                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9278                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9279                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9280                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9281                 }
9282                 dynamicvertex = true;
9283                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
9284         }
9285
9286         // when the model data has no vertex buffer (dynamic mesh), we need to
9287         // eliminate gaps
9288         if (vid.useinterleavedarrays && !rsurface.modelvertexmesh_vertexbuffer)
9289                 batchneed |= BATCHNEED_NOGAPS;
9290
9291         // the caller can specify BATCHNEED_NOGAPS to force a batch with
9292         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
9293         // we ensure this by treating the vertex batch as dynamic...
9294         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
9295         {
9296                 if (!dynamicvertex)
9297                 {
9298                         r_refdef.stats[r_stat_batch_dynamic_batches_because_nogaps] += 1;
9299                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_nogaps] += batchnumsurfaces;
9300                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_nogaps] += batchnumvertices;
9301                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_nogaps] += batchnumtriangles;
9302                 }
9303                 dynamicvertex = true;
9304         }
9305
9306         if (dynamicvertex)
9307         {
9308                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
9309                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
9310                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
9311                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
9312                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
9313                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
9314                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
9315                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
9316         }
9317
9318         // if needsupdate, we have to do a dynamic vertex batch for sure
9319         if (needsupdate & batchneed)
9320         {
9321                 if (!dynamicvertex)
9322                 {
9323                         r_refdef.stats[r_stat_batch_dynamic_batches_because_derived] += 1;
9324                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_derived] += batchnumsurfaces;
9325                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_derived] += batchnumvertices;
9326                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_derived] += batchnumtriangles;
9327                 }
9328                 dynamicvertex = true;
9329         }
9330
9331         // see if we need to build vertexmesh from arrays
9332         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
9333         {
9334                 if (!dynamicvertex)
9335                 {
9336                         r_refdef.stats[r_stat_batch_dynamic_batches_because_interleavedarrays] += 1;
9337                         r_refdef.stats[r_stat_batch_dynamic_surfaces_because_interleavedarrays] += batchnumsurfaces;
9338                         r_refdef.stats[r_stat_batch_dynamic_vertices_because_interleavedarrays] += batchnumvertices;
9339                         r_refdef.stats[r_stat_batch_dynamic_triangles_because_interleavedarrays] += batchnumtriangles;
9340                 }
9341                 dynamicvertex = true;
9342         }
9343
9344         // if we're going to have to apply the skeletal transform manually, we need to batch the skeletal data
9345         if (dynamicvertex && rsurface.entityskeletaltransform3x4)
9346                 batchneed |= BATCHNEED_ARRAY_SKELETAL;
9347
9348         rsurface.batchvertex3f = rsurface.modelvertex3f;
9349         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
9350         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
9351         rsurface.batchsvector3f = rsurface.modelsvector3f;
9352         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
9353         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
9354         rsurface.batchtvector3f = rsurface.modeltvector3f;
9355         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
9356         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
9357         rsurface.batchnormal3f = rsurface.modelnormal3f;
9358         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
9359         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
9360         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
9361         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
9362         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
9363         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
9364         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
9365         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
9366         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
9367         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
9368         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
9369         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
9370         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
9371         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
9372         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
9373         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
9374         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
9375         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
9376         rsurface.batchvertexmesh_vertexbuffer = rsurface.modelvertexmesh_vertexbuffer;
9377         rsurface.batchvertexmesh_bufferoffset = rsurface.modelvertexmesh_bufferoffset;
9378         rsurface.batchelement3i = rsurface.modelelement3i;
9379         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
9380         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
9381         rsurface.batchelement3s = rsurface.modelelement3s;
9382         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
9383         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
9384         rsurface.batchskeletaltransform3x4 = rsurface.entityskeletaltransform3x4;
9385         rsurface.batchskeletaltransform3x4buffer = rsurface.entityskeletaltransform3x4buffer;
9386         rsurface.batchskeletaltransform3x4offset = rsurface.entityskeletaltransform3x4offset;
9387         rsurface.batchskeletaltransform3x4size = rsurface.entityskeletaltransform3x4size;
9388         rsurface.batchskeletalnumtransforms = rsurface.entityskeletalnumtransforms;
9389
9390         // if any dynamic vertex processing has to occur in software, we copy the
9391         // entire surface list together before processing to rebase the vertices
9392         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
9393         //
9394         // if any gaps exist and we do not have a static vertex buffer, we have to
9395         // copy the surface list together to avoid wasting upload bandwidth on the
9396         // vertices in the gaps.
9397         //
9398         // if gaps exist and we have a static vertex buffer, we can choose whether
9399         // to combine the index buffer ranges into one dynamic index buffer or
9400         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
9401         //
9402         // in many cases the batch is reduced to one draw call.
9403
9404         rsurface.batchmultidraw = false;
9405         rsurface.batchmultidrawnumsurfaces = 0;
9406         rsurface.batchmultidrawsurfacelist = NULL;
9407
9408         if (!dynamicvertex)
9409         {
9410                 // static vertex data, just set pointers...
9411                 rsurface.batchgeneratedvertex = false;
9412                 // if there are gaps, we want to build a combined index buffer,
9413                 // otherwise use the original static buffer with an appropriate offset
9414                 if (gaps)
9415                 {
9416                         r_refdef.stats[r_stat_batch_copytriangles_batches] += 1;
9417                         r_refdef.stats[r_stat_batch_copytriangles_surfaces] += batchnumsurfaces;
9418                         r_refdef.stats[r_stat_batch_copytriangles_vertices] += batchnumvertices;
9419                         r_refdef.stats[r_stat_batch_copytriangles_triangles] += batchnumtriangles;
9420                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
9421                         {
9422                                 rsurface.batchmultidraw = true;
9423                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
9424                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
9425                                 return;
9426                         }
9427                         // build a new triangle elements array for this batch
9428                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9429                         rsurface.batchfirsttriangle = 0;
9430                         numtriangles = 0;
9431                         for (i = 0;i < texturenumsurfaces;i++)
9432                         {
9433                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9434                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9435                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
9436                                 numtriangles += surfacenumtriangles;
9437                         }
9438                         rsurface.batchelement3i_indexbuffer = NULL;
9439                         rsurface.batchelement3i_bufferoffset = 0;
9440                         rsurface.batchelement3s = NULL;
9441                         rsurface.batchelement3s_indexbuffer = NULL;
9442                         rsurface.batchelement3s_bufferoffset = 0;
9443                         if (endvertex <= 65536)
9444                         {
9445                                 // make a 16bit (unsigned short) index array if possible
9446                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9447                                 for (i = 0;i < numtriangles*3;i++)
9448                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9449                         }
9450                         // upload buffer data for the copytriangles batch
9451                         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
9452                         {
9453                                 if (rsurface.batchelement3s)
9454                                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
9455                                 else if (rsurface.batchelement3i)
9456                                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
9457                         }
9458                 }
9459                 else
9460                 {
9461                         r_refdef.stats[r_stat_batch_fast_batches] += 1;
9462                         r_refdef.stats[r_stat_batch_fast_surfaces] += batchnumsurfaces;
9463                         r_refdef.stats[r_stat_batch_fast_vertices] += batchnumvertices;
9464                         r_refdef.stats[r_stat_batch_fast_triangles] += batchnumtriangles;
9465                 }
9466                 return;
9467         }
9468
9469         // something needs software processing, do it for real...
9470         // we only directly handle separate array data in this case and then
9471         // generate interleaved data if needed...
9472         rsurface.batchgeneratedvertex = true;
9473         r_refdef.stats[r_stat_batch_dynamic_batches] += 1;
9474         r_refdef.stats[r_stat_batch_dynamic_surfaces] += batchnumsurfaces;
9475         r_refdef.stats[r_stat_batch_dynamic_vertices] += batchnumvertices;
9476         r_refdef.stats[r_stat_batch_dynamic_triangles] += batchnumtriangles;
9477
9478         // now copy the vertex data into a combined array and make an index array
9479         // (this is what Quake3 does all the time)
9480         // we also apply any skeletal animation here that would have been done in
9481         // the vertex shader, because most of the dynamic vertex animation cases
9482         // need actual vertex positions and normals
9483         //if (dynamicvertex)
9484         {
9485                 rsurface.batchvertexmesh = NULL;
9486                 rsurface.batchvertexmesh_vertexbuffer = NULL;
9487                 rsurface.batchvertexmesh_bufferoffset = 0;
9488                 rsurface.batchvertex3f = NULL;
9489                 rsurface.batchvertex3f_vertexbuffer = NULL;
9490                 rsurface.batchvertex3f_bufferoffset = 0;
9491                 rsurface.batchsvector3f = NULL;
9492                 rsurface.batchsvector3f_vertexbuffer = NULL;
9493                 rsurface.batchsvector3f_bufferoffset = 0;
9494                 rsurface.batchtvector3f = NULL;
9495                 rsurface.batchtvector3f_vertexbuffer = NULL;
9496                 rsurface.batchtvector3f_bufferoffset = 0;
9497                 rsurface.batchnormal3f = NULL;
9498                 rsurface.batchnormal3f_vertexbuffer = NULL;
9499                 rsurface.batchnormal3f_bufferoffset = 0;
9500                 rsurface.batchlightmapcolor4f = NULL;
9501                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9502                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9503                 rsurface.batchtexcoordtexture2f = NULL;
9504                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9505                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9506                 rsurface.batchtexcoordlightmap2f = NULL;
9507                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9508                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9509                 rsurface.batchskeletalindex4ub = NULL;
9510                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9511                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9512                 rsurface.batchskeletalweight4ub = NULL;
9513                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9514                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9515                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9516                 rsurface.batchelement3i_indexbuffer = NULL;
9517                 rsurface.batchelement3i_bufferoffset = 0;
9518                 rsurface.batchelement3s = NULL;
9519                 rsurface.batchelement3s_indexbuffer = NULL;
9520                 rsurface.batchelement3s_bufferoffset = 0;
9521                 rsurface.batchskeletaltransform3x4buffer = NULL;
9522                 rsurface.batchskeletaltransform3x4offset = 0;
9523                 rsurface.batchskeletaltransform3x4size = 0;
9524                 // we'll only be setting up certain arrays as needed
9525                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9526                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9527                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9528                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9529                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9530                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9531                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9532                 {
9533                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9534                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9535                 }
9536                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9537                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9538                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9539                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9540                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9541                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9542                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9543                 {
9544                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9545                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9546                 }
9547                 numvertices = 0;
9548                 numtriangles = 0;
9549                 for (i = 0;i < texturenumsurfaces;i++)
9550                 {
9551                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9552                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9553                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9554                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9555                         // copy only the data requested
9556                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9557                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9558                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9559                         {
9560                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9561                                 {
9562                                         if (rsurface.batchvertex3f)
9563                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9564                                         else
9565                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9566                                 }
9567                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9568                                 {
9569                                         if (rsurface.modelnormal3f)
9570                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9571                                         else
9572                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9573                                 }
9574                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9575                                 {
9576                                         if (rsurface.modelsvector3f)
9577                                         {
9578                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9579                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9580                                         }
9581                                         else
9582                                         {
9583                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9584                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9585                                         }
9586                                 }
9587                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9588                                 {
9589                                         if (rsurface.modellightmapcolor4f)
9590                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9591                                         else
9592                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9593                                 }
9594                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9595                                 {
9596                                         if (rsurface.modeltexcoordtexture2f)
9597                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9598                                         else
9599                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9600                                 }
9601                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9602                                 {
9603                                         if (rsurface.modeltexcoordlightmap2f)
9604                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9605                                         else
9606                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9607                                 }
9608                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9609                                 {
9610                                         if (rsurface.modelskeletalindex4ub)
9611                                         {
9612                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9613                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9614                                         }
9615                                         else
9616                                         {
9617                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9618                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9619                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9620                                                 for (j = 0;j < surfacenumvertices;j++)
9621                                                         ub[j*4] = 255;
9622                                         }
9623                                 }
9624                         }
9625                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9626                         numvertices += surfacenumvertices;
9627                         numtriangles += surfacenumtriangles;
9628                 }
9629
9630                 // generate a 16bit index array as well if possible
9631                 // (in general, dynamic batches fit)
9632                 if (numvertices <= 65536)
9633                 {
9634                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9635                         for (i = 0;i < numtriangles*3;i++)
9636                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9637                 }
9638
9639                 // since we've copied everything, the batch now starts at 0
9640                 rsurface.batchfirstvertex = 0;
9641                 rsurface.batchnumvertices = batchnumvertices;
9642                 rsurface.batchfirsttriangle = 0;
9643                 rsurface.batchnumtriangles = batchnumtriangles;
9644         }
9645
9646         // apply skeletal animation that would have been done in the vertex shader
9647         if (rsurface.batchskeletaltransform3x4)
9648         {
9649                 const unsigned char *si;
9650                 const unsigned char *sw;
9651                 const float *t[4];
9652                 const float *b = rsurface.batchskeletaltransform3x4;
9653                 float *vp, *vs, *vt, *vn;
9654                 float w[4];
9655                 float m[3][4], n[3][4];
9656                 float tp[3], ts[3], tt[3], tn[3];
9657                 r_refdef.stats[r_stat_batch_dynamicskeletal_batches] += 1;
9658                 r_refdef.stats[r_stat_batch_dynamicskeletal_surfaces] += batchnumsurfaces;
9659                 r_refdef.stats[r_stat_batch_dynamicskeletal_vertices] += batchnumvertices;
9660                 r_refdef.stats[r_stat_batch_dynamicskeletal_triangles] += batchnumtriangles;
9661                 si = rsurface.batchskeletalindex4ub;
9662                 sw = rsurface.batchskeletalweight4ub;
9663                 vp = rsurface.batchvertex3f;
9664                 vs = rsurface.batchsvector3f;
9665                 vt = rsurface.batchtvector3f;
9666                 vn = rsurface.batchnormal3f;
9667                 memset(m[0], 0, sizeof(m));
9668                 memset(n[0], 0, sizeof(n));
9669                 for (i = 0;i < batchnumvertices;i++)
9670                 {
9671                         t[0] = b + si[0]*12;
9672                         if (sw[0] == 255)
9673                         {
9674                                 // common case - only one matrix
9675                                 m[0][0] = t[0][ 0];
9676                                 m[0][1] = t[0][ 1];
9677                                 m[0][2] = t[0][ 2];
9678                                 m[0][3] = t[0][ 3];
9679                                 m[1][0] = t[0][ 4];
9680                                 m[1][1] = t[0][ 5];
9681                                 m[1][2] = t[0][ 6];
9682                                 m[1][3] = t[0][ 7];
9683                                 m[2][0] = t[0][ 8];
9684                                 m[2][1] = t[0][ 9];
9685                                 m[2][2] = t[0][10];
9686                                 m[2][3] = t[0][11];
9687                         }
9688                         else if (sw[2] + sw[3])
9689                         {
9690                                 // blend 4 matrices
9691                                 t[1] = b + si[1]*12;
9692                                 t[2] = b + si[2]*12;
9693                                 t[3] = b + si[3]*12;
9694                                 w[0] = sw[0] * (1.0f / 255.0f);
9695                                 w[1] = sw[1] * (1.0f / 255.0f);
9696                                 w[2] = sw[2] * (1.0f / 255.0f);
9697                                 w[3] = sw[3] * (1.0f / 255.0f);
9698                                 // blend the matrices
9699                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1] + t[2][ 0] * w[2] + t[3][ 0] * w[3];
9700                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1] + t[2][ 1] * w[2] + t[3][ 1] * w[3];
9701                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1] + t[2][ 2] * w[2] + t[3][ 2] * w[3];
9702                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1] + t[2][ 3] * w[2] + t[3][ 3] * w[3];
9703                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1] + t[2][ 4] * w[2] + t[3][ 4] * w[3];
9704                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1] + t[2][ 5] * w[2] + t[3][ 5] * w[3];
9705                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1] + t[2][ 6] * w[2] + t[3][ 6] * w[3];
9706                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1] + t[2][ 7] * w[2] + t[3][ 7] * w[3];
9707                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1] + t[2][ 8] * w[2] + t[3][ 8] * w[3];
9708                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1] + t[2][ 9] * w[2] + t[3][ 9] * w[3];
9709                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1] + t[2][10] * w[2] + t[3][10] * w[3];
9710                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1] + t[2][11] * w[2] + t[3][11] * w[3];
9711                         }
9712                         else
9713                         {
9714                                 // blend 2 matrices
9715                                 t[1] = b + si[1]*12;
9716                                 w[0] = sw[0] * (1.0f / 255.0f);
9717                                 w[1] = sw[1] * (1.0f / 255.0f);
9718                                 // blend the matrices
9719                                 m[0][0] = t[0][ 0] * w[0] + t[1][ 0] * w[1];
9720                                 m[0][1] = t[0][ 1] * w[0] + t[1][ 1] * w[1];
9721                                 m[0][2] = t[0][ 2] * w[0] + t[1][ 2] * w[1];
9722                                 m[0][3] = t[0][ 3] * w[0] + t[1][ 3] * w[1];
9723                                 m[1][0] = t[0][ 4] * w[0] + t[1][ 4] * w[1];
9724                                 m[1][1] = t[0][ 5] * w[0] + t[1][ 5] * w[1];
9725                                 m[1][2] = t[0][ 6] * w[0] + t[1][ 6] * w[1];
9726                                 m[1][3] = t[0][ 7] * w[0] + t[1][ 7] * w[1];
9727                                 m[2][0] = t[0][ 8] * w[0] + t[1][ 8] * w[1];
9728                                 m[2][1] = t[0][ 9] * w[0] + t[1][ 9] * w[1];
9729                                 m[2][2] = t[0][10] * w[0] + t[1][10] * w[1];
9730                                 m[2][3] = t[0][11] * w[0] + t[1][11] * w[1];
9731                         }
9732                         si += 4;
9733                         sw += 4;
9734                         // modify the vertex
9735                         VectorCopy(vp, tp);
9736                         vp[0] = tp[0] * m[0][0] + tp[1] * m[0][1] + tp[2] * m[0][2] + m[0][3];
9737                         vp[1] = tp[0] * m[1][0] + tp[1] * m[1][1] + tp[2] * m[1][2] + m[1][3];
9738                         vp[2] = tp[0] * m[2][0] + tp[1] * m[2][1] + tp[2] * m[2][2] + m[2][3];
9739                         vp += 3;
9740                         if (vn)
9741                         {
9742                                 // the normal transformation matrix is a set of cross products...
9743                                 CrossProduct(m[1], m[2], n[0]);
9744                                 CrossProduct(m[2], m[0], n[1]);
9745                                 CrossProduct(m[0], m[1], n[2]); // is actually transpose(inverse(m)) * det(m)
9746                                 VectorCopy(vn, tn);
9747                                 vn[0] = tn[0] * n[0][0] + tn[1] * n[0][1] + tn[2] * n[0][2];
9748                                 vn[1] = tn[0] * n[1][0] + tn[1] * n[1][1] + tn[2] * n[1][2];
9749                                 vn[2] = tn[0] * n[2][0] + tn[1] * n[2][1] + tn[2] * n[2][2];
9750                                 VectorNormalize(vn);
9751                                 vn += 3;
9752                                 if (vs)
9753                                 {
9754                                         VectorCopy(vs, ts);
9755                                         vs[0] = ts[0] * n[0][0] + ts[1] * n[0][1] + ts[2] * n[0][2];
9756                                         vs[1] = ts[0] * n[1][0] + ts[1] * n[1][1] + ts[2] * n[1][2];
9757                                         vs[2] = ts[0] * n[2][0] + ts[1] * n[2][1] + ts[2] * n[2][2];
9758                                         VectorNormalize(vs);
9759                                         vs += 3;
9760                                         VectorCopy(vt, tt);
9761                                         vt[0] = tt[0] * n[0][0] + tt[1] * n[0][1] + tt[2] * n[0][2];
9762                                         vt[1] = tt[0] * n[1][0] + tt[1] * n[1][1] + tt[2] * n[1][2];
9763                                         vt[2] = tt[0] * n[2][0] + tt[1] * n[2][1] + tt[2] * n[2][2];
9764                                         VectorNormalize(vt);
9765                                         vt += 3;
9766                                 }
9767                         }
9768                 }
9769                 rsurface.batchskeletaltransform3x4 = NULL;
9770                 rsurface.batchskeletalnumtransforms = 0;
9771         }
9772
9773         // q1bsp surfaces rendered in vertex color mode have to have colors
9774         // calculated based on lightstyles
9775         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9776         {
9777                 // generate color arrays for the surfaces in this list
9778                 int c[4];
9779                 int scale;
9780                 int size3;
9781                 const int *offsets;
9782                 const unsigned char *lm;
9783                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9784                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9785                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9786                 numvertices = 0;
9787                 for (i = 0;i < texturenumsurfaces;i++)
9788                 {
9789                         surface = texturesurfacelist[i];
9790                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9791                         surfacenumvertices = surface->num_vertices;
9792                         if (surface->lightmapinfo->samples)
9793                         {
9794                                 for (j = 0;j < surfacenumvertices;j++)
9795                                 {
9796                                         lm = surface->lightmapinfo->samples + offsets[j];
9797                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9798                                         VectorScale(lm, scale, c);
9799                                         if (surface->lightmapinfo->styles[1] != 255)
9800                                         {
9801                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9802                                                 lm += size3;
9803                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9804                                                 VectorMA(c, scale, lm, c);
9805                                                 if (surface->lightmapinfo->styles[2] != 255)
9806                                                 {
9807                                                         lm += size3;
9808                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9809                                                         VectorMA(c, scale, lm, c);
9810                                                         if (surface->lightmapinfo->styles[3] != 255)
9811                                                         {
9812                                                                 lm += size3;
9813                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9814                                                                 VectorMA(c, scale, lm, c);
9815                                                         }
9816                                                 }
9817                                         }
9818                                         c[0] >>= 7;
9819                                         c[1] >>= 7;
9820                                         c[2] >>= 7;
9821                                         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);
9822                                         numvertices++;
9823                                 }
9824                         }
9825                         else
9826                         {
9827                                 for (j = 0;j < surfacenumvertices;j++)
9828                                 {
9829                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9830                                         numvertices++;
9831                                 }
9832                         }
9833                 }
9834         }
9835
9836         // if vertices are deformed (sprite flares and things in maps, possibly
9837         // water waves, bulges and other deformations), modify the copied vertices
9838         // in place
9839         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9840         {
9841                 switch (deform->deform)
9842                 {
9843                 default:
9844                 case Q3DEFORM_PROJECTIONSHADOW:
9845                 case Q3DEFORM_TEXT0:
9846                 case Q3DEFORM_TEXT1:
9847                 case Q3DEFORM_TEXT2:
9848                 case Q3DEFORM_TEXT3:
9849                 case Q3DEFORM_TEXT4:
9850                 case Q3DEFORM_TEXT5:
9851                 case Q3DEFORM_TEXT6:
9852                 case Q3DEFORM_TEXT7:
9853                 case Q3DEFORM_NONE:
9854                         break;
9855                 case Q3DEFORM_AUTOSPRITE:
9856                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9857                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9858                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9859                         VectorNormalize(newforward);
9860                         VectorNormalize(newright);
9861                         VectorNormalize(newup);
9862 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9863 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9864 //                      rsurface.batchvertex3f_bufferoffset = 0;
9865 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9866 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9867 //                      rsurface.batchsvector3f_bufferoffset = 0;
9868 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9869 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9870 //                      rsurface.batchtvector3f_bufferoffset = 0;
9871 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9872 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9873 //                      rsurface.batchnormal3f_bufferoffset = 0;
9874                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9875                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9876                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9877                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9878                                 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);
9879                         // a single autosprite surface can contain multiple sprites...
9880                         for (j = 0;j < batchnumvertices - 3;j += 4)
9881                         {
9882                                 VectorClear(center);
9883                                 for (i = 0;i < 4;i++)
9884                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9885                                 VectorScale(center, 0.25f, center);
9886                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9887                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9888                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9889                                 for (i = 0;i < 4;i++)
9890                                 {
9891                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9892                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9893                                 }
9894                         }
9895                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9896                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9897                         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);
9898                         break;
9899                 case Q3DEFORM_AUTOSPRITE2:
9900                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9901                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9902                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9903                         VectorNormalize(newforward);
9904                         VectorNormalize(newright);
9905                         VectorNormalize(newup);
9906 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9907 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9908 //                      rsurface.batchvertex3f_bufferoffset = 0;
9909                         {
9910                                 const float *v1, *v2;
9911                                 vec3_t start, end;
9912                                 float f, l;
9913                                 struct
9914                                 {
9915                                         float length2;
9916                                         const float *v1;
9917                                         const float *v2;
9918                                 }
9919                                 shortest[2];
9920                                 memset(shortest, 0, sizeof(shortest));
9921                                 // a single autosprite surface can contain multiple sprites...
9922                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9923                                 {
9924                                         VectorClear(center);
9925                                         for (i = 0;i < 4;i++)
9926                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9927                                         VectorScale(center, 0.25f, center);
9928                                         // find the two shortest edges, then use them to define the
9929                                         // axis vectors for rotating around the central axis
9930                                         for (i = 0;i < 6;i++)
9931                                         {
9932                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9933                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9934                                                 l = VectorDistance2(v1, v2);
9935                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9936                                                 if (v1[2] != v2[2])
9937                                                         l += (1.0f / 1024.0f);
9938                                                 if (shortest[0].length2 > l || i == 0)
9939                                                 {
9940                                                         shortest[1] = shortest[0];
9941                                                         shortest[0].length2 = l;
9942                                                         shortest[0].v1 = v1;
9943                                                         shortest[0].v2 = v2;
9944                                                 }
9945                                                 else if (shortest[1].length2 > l || i == 1)
9946                                                 {
9947                                                         shortest[1].length2 = l;
9948                                                         shortest[1].v1 = v1;
9949                                                         shortest[1].v2 = v2;
9950                                                 }
9951                                         }
9952                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9953                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9954                                         // this calculates the right vector from the shortest edge
9955                                         // and the up vector from the edge midpoints
9956                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9957                                         VectorNormalize(right);
9958                                         VectorSubtract(end, start, up);
9959                                         VectorNormalize(up);
9960                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9961                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9962                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9963                                         VectorNegate(forward, forward);
9964                                         VectorReflect(forward, 0, up, forward);
9965                                         VectorNormalize(forward);
9966                                         CrossProduct(up, forward, newright);
9967                                         VectorNormalize(newright);
9968                                         // rotate the quad around the up axis vector, this is made
9969                                         // especially easy by the fact we know the quad is flat,
9970                                         // so we only have to subtract the center position and
9971                                         // measure distance along the right vector, and then
9972                                         // multiply that by the newright vector and add back the
9973                                         // center position
9974                                         // we also need to subtract the old position to undo the
9975                                         // displacement from the center, which we do with a
9976                                         // DotProduct, the subtraction/addition of center is also
9977                                         // optimized into DotProducts here
9978                                         l = DotProduct(right, center);
9979                                         for (i = 0;i < 4;i++)
9980                                         {
9981                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9982                                                 f = DotProduct(right, v1) - l;
9983                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9984                                         }
9985                                 }
9986                         }
9987                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9988                         {
9989 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9990 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9991 //                              rsurface.batchnormal3f_bufferoffset = 0;
9992                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9993                         }
9994                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9995                         {
9996 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9997 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9998 //                              rsurface.batchsvector3f_bufferoffset = 0;
9999 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10000 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10001 //                              rsurface.batchtvector3f_bufferoffset = 0;
10002                                 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);
10003                         }
10004                         break;
10005                 case Q3DEFORM_NORMAL:
10006                         // deform the normals to make reflections wavey
10007                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10008                         rsurface.batchnormal3f_vertexbuffer = NULL;
10009                         rsurface.batchnormal3f_bufferoffset = 0;
10010                         for (j = 0;j < batchnumvertices;j++)
10011                         {
10012                                 float vertex[3];
10013                                 float *normal = rsurface.batchnormal3f + 3*j;
10014                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
10015                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10016                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10017                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
10018                                 VectorNormalize(normal);
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_WAVE:
10032                         // deform vertex array to make wavey water and flags and such
10033                         waveparms[0] = deform->waveparms[0];
10034                         waveparms[1] = deform->waveparms[1];
10035                         waveparms[2] = deform->waveparms[2];
10036                         waveparms[3] = deform->waveparms[3];
10037                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
10038                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10039                         // this is how a divisor of vertex influence on deformation
10040                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
10041                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10042 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10043 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10044 //                      rsurface.batchvertex3f_bufferoffset = 0;
10045 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10046 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10047 //                      rsurface.batchnormal3f_bufferoffset = 0;
10048                         for (j = 0;j < batchnumvertices;j++)
10049                         {
10050                                 // if the wavefunc depends on time, evaluate it per-vertex
10051                                 if (waveparms[3])
10052                                 {
10053                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
10054                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
10055                                 }
10056                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
10057                         }
10058                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
10059                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
10060                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
10061                         {
10062 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10063 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
10064 //                              rsurface.batchsvector3f_bufferoffset = 0;
10065 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
10066 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
10067 //                              rsurface.batchtvector3f_bufferoffset = 0;
10068                                 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);
10069                         }
10070                         break;
10071                 case Q3DEFORM_BULGE:
10072                         // deform vertex array to make the surface have moving bulges
10073 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10074 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10075 //                      rsurface.batchvertex3f_bufferoffset = 0;
10076 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
10077 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
10078 //                      rsurface.batchnormal3f_bufferoffset = 0;
10079                         for (j = 0;j < batchnumvertices;j++)
10080                         {
10081                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
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_MOVE:
10098                         // deform vertex array
10099                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
10100                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
10101                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
10102                         VectorScale(deform->parms, scale, waveparms);
10103 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
10104 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
10105 //                      rsurface.batchvertex3f_bufferoffset = 0;
10106                         for (j = 0;j < batchnumvertices;j++)
10107                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
10108                         break;
10109                 }
10110         }
10111
10112         if (rsurface.batchtexcoordtexture2f)
10113         {
10114         // generate texcoords based on the chosen texcoord source
10115                 switch(rsurface.texture->tcgen.tcgen)
10116                 {
10117                 default:
10118                 case Q3TCGEN_TEXTURE:
10119                         break;
10120                 case Q3TCGEN_LIGHTMAP:
10121         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10122         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10123         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10124                         if (rsurface.batchtexcoordlightmap2f)
10125                                 memcpy(rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f, batchnumvertices * sizeof(float[2]));
10126                         break;
10127                 case Q3TCGEN_VECTOR:
10128         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10129         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10130         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10131                         for (j = 0;j < batchnumvertices;j++)
10132                         {
10133                                 rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
10134                                 rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
10135                         }
10136                         break;
10137                 case Q3TCGEN_ENVIRONMENT:
10138                         // make environment reflections using a spheremap
10139                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10140                         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10141                         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10142                         for (j = 0;j < batchnumvertices;j++)
10143                         {
10144                                 // identical to Q3A's method, but executed in worldspace so
10145                                 // carried models can be shiny too
10146
10147                                 float viewer[3], d, reflected[3], worldreflected[3];
10148
10149                                 VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
10150                                 // VectorNormalize(viewer);
10151
10152                                 d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
10153
10154                                 reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
10155                                 reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
10156                                 reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
10157                                 // note: this is proportinal to viewer, so we can normalize later
10158
10159                                 Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
10160                                 VectorNormalize(worldreflected);
10161
10162                                 // note: this sphere map only uses world x and z!
10163                                 // so positive and negative y will LOOK THE SAME.
10164                                 rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
10165                                 rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
10166                         }
10167                         break;
10168                 }
10169                 // the only tcmod that needs software vertex processing is turbulent, so
10170                 // check for it here and apply the changes if needed
10171                 // and we only support that as the first one
10172                 // (handling a mixture of turbulent and other tcmods would be problematic
10173                 //  without punting it entirely to a software path)
10174                 if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
10175                 {
10176                         amplitude = rsurface.texture->tcmods[0].parms[1];
10177                         animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
10178         //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
10179         //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
10180         //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
10181                         for (j = 0;j < batchnumvertices;j++)
10182                         {
10183                                 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);
10184                                 rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
10185                         }
10186                 }
10187         }
10188
10189         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
10190         {
10191                 // convert the modified arrays to vertex structs
10192 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
10193 //              rsurface.batchvertexmesh_vertexbuffer = NULL;
10194 //              rsurface.batchvertexmesh_bufferoffset = 0;
10195                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
10196                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10197                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
10198                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
10199                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10200                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
10201                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
10202                 {
10203                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10204                         {
10205                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
10206                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
10207                         }
10208                 }
10209                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
10210                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10211                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
10212                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
10213                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10214                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
10215                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
10216                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10217                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
10218                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
10219                 {
10220                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
10221                         {
10222                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
10223                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
10224                         }
10225                 }
10226         }
10227
10228         // upload buffer data for the dynamic batch
10229         if (((r_batch_dynamicbuffer.integer || gl_vbo_dynamicvertex.integer || gl_vbo_dynamicindex.integer) && vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo)
10230         {
10231                 if (rsurface.batchvertexmesh)
10232                         rsurface.batchvertexmesh_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(r_vertexmesh_t), rsurface.batchvertexmesh, R_BUFFERDATA_VERTEX, &rsurface.batchvertexmesh_bufferoffset);
10233                 else
10234                 {
10235                         if (rsurface.batchvertex3f)
10236                                 rsurface.batchvertex3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f, R_BUFFERDATA_VERTEX, &rsurface.batchvertex3f_bufferoffset);
10237                         if (rsurface.batchsvector3f)
10238                                 rsurface.batchsvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchsvector3f_bufferoffset);
10239                         if (rsurface.batchtvector3f)
10240                                 rsurface.batchtvector3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f, R_BUFFERDATA_VERTEX, &rsurface.batchtvector3f_bufferoffset);
10241                         if (rsurface.batchnormal3f)
10242                                 rsurface.batchnormal3f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f, R_BUFFERDATA_VERTEX, &rsurface.batchnormal3f_bufferoffset);
10243                         if (rsurface.batchlightmapcolor4f)
10244                                 rsurface.batchlightmapcolor4f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[4]), rsurface.batchlightmapcolor4f, R_BUFFERDATA_VERTEX, &rsurface.batchlightmapcolor4f_bufferoffset);
10245                         if (rsurface.batchtexcoordtexture2f)
10246                                 rsurface.batchtexcoordtexture2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordtexture2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordtexture2f_bufferoffset);
10247                         if (rsurface.batchtexcoordlightmap2f)
10248                                 rsurface.batchtexcoordlightmap2f_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(float[2]), rsurface.batchtexcoordlightmap2f, R_BUFFERDATA_VERTEX, &rsurface.batchtexcoordlightmap2f_bufferoffset);
10249                         if (rsurface.batchskeletalindex4ub)
10250                                 rsurface.batchskeletalindex4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalindex4ub_bufferoffset);
10251                         if (rsurface.batchskeletalweight4ub)
10252                                 rsurface.batchskeletalweight4ub_vertexbuffer = R_BufferData_Store(rsurface.batchnumvertices * sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, R_BUFFERDATA_VERTEX, &rsurface.batchskeletalweight4ub_bufferoffset);
10253                 }
10254                 if (rsurface.batchelement3s)
10255                         rsurface.batchelement3s_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(short[3]), rsurface.batchelement3s, R_BUFFERDATA_INDEX16, &rsurface.batchelement3s_bufferoffset);
10256                 else if (rsurface.batchelement3i)
10257                         rsurface.batchelement3i_indexbuffer = R_BufferData_Store(rsurface.batchnumtriangles * sizeof(int[3]), rsurface.batchelement3i, R_BUFFERDATA_INDEX32, &rsurface.batchelement3i_bufferoffset);
10258         }
10259 }
10260
10261 void RSurf_DrawBatch(void)
10262 {
10263         // sometimes a zero triangle surface (usually a degenerate patch) makes it
10264         // through the pipeline, killing it earlier in the pipeline would have
10265         // per-surface overhead rather than per-batch overhead, so it's best to
10266         // reject it here, before it hits glDraw.
10267         if (rsurface.batchnumtriangles == 0)
10268                 return;
10269 #if 0
10270         // batch debugging code
10271         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
10272         {
10273                 int i;
10274                 int j;
10275                 int c;
10276                 const int *e;
10277                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
10278                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
10279                 {
10280                         c = e[i];
10281                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
10282                         {
10283                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
10284                                 {
10285                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
10286                                                 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);
10287                                         break;
10288                                 }
10289                         }
10290                 }
10291         }
10292 #endif
10293         if (rsurface.batchmultidraw)
10294         {
10295                 // issue multiple draws rather than copying index data
10296                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
10297                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
10298                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
10299                 for (i = 0;i < numsurfaces;)
10300                 {
10301                         // combine consecutive surfaces as one draw
10302                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
10303                                 if (surfacelist[j] != surfacelist[k] + 1)
10304                                         break;
10305                         firstvertex = surfacelist[i]->num_firstvertex;
10306                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
10307                         firsttriangle = surfacelist[i]->num_firsttriangle;
10308                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
10309                         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);
10310                         i = j;
10311                 }
10312         }
10313         else
10314         {
10315                 // there is only one consecutive run of index data (may have been combined)
10316                 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);
10317         }
10318 }
10319
10320 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
10321 {
10322         // pick the closest matching water plane
10323         int planeindex, vertexindex, bestplaneindex = -1;
10324         float d, bestd;
10325         vec3_t vert;
10326         const float *v;
10327         r_waterstate_waterplane_t *p;
10328         qboolean prepared = false;
10329         bestd = 0;
10330         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
10331         {
10332                 if(p->camera_entity != rsurface.texture->camera_entity)
10333                         continue;
10334                 d = 0;
10335                 if(!prepared)
10336                 {
10337                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
10338                         prepared = true;
10339                         if(rsurface.batchnumvertices == 0)
10340                                 break;
10341                 }
10342                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
10343                 {
10344                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
10345                         d += fabs(PlaneDiff(vert, &p->plane));
10346                 }
10347                 if (bestd > d || bestplaneindex < 0)
10348                 {
10349                         bestd = d;
10350                         bestplaneindex = planeindex;
10351                 }
10352         }
10353         return bestplaneindex;
10354         // NOTE: this MAY return a totally unrelated water plane; we can ignore
10355         // this situation though, as it might be better to render single larger
10356         // batches with useless stuff (backface culled for example) than to
10357         // render multiple smaller batches
10358 }
10359
10360 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
10361 {
10362         int i;
10363         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10364         rsurface.passcolor4f_vertexbuffer = 0;
10365         rsurface.passcolor4f_bufferoffset = 0;
10366         for (i = 0;i < rsurface.batchnumvertices;i++)
10367                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
10368 }
10369
10370 static void RSurf_DrawBatch_GL11_ApplyFog(void)
10371 {
10372         int i;
10373         float f;
10374         const float *v;
10375         const float *c;
10376         float *c2;
10377         if (rsurface.passcolor4f)
10378         {
10379                 // generate color arrays
10380                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10381                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10382                 rsurface.passcolor4f_vertexbuffer = 0;
10383                 rsurface.passcolor4f_bufferoffset = 0;
10384                 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)
10385                 {
10386                         f = RSurf_FogVertex(v);
10387                         c2[0] = c[0] * f;
10388                         c2[1] = c[1] * f;
10389                         c2[2] = c[2] * f;
10390                         c2[3] = c[3];
10391                 }
10392         }
10393         else
10394         {
10395                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10396                 rsurface.passcolor4f_vertexbuffer = 0;
10397                 rsurface.passcolor4f_bufferoffset = 0;
10398                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
10399                 {
10400                         f = RSurf_FogVertex(v);
10401                         c2[0] = f;
10402                         c2[1] = f;
10403                         c2[2] = f;
10404                         c2[3] = 1;
10405                 }
10406         }
10407 }
10408
10409 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
10410 {
10411         int i;
10412         float f;
10413         const float *v;
10414         const float *c;
10415         float *c2;
10416         if (!rsurface.passcolor4f)
10417                 return;
10418         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10419         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10420         rsurface.passcolor4f_vertexbuffer = 0;
10421         rsurface.passcolor4f_bufferoffset = 0;
10422         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)
10423         {
10424                 f = RSurf_FogVertex(v);
10425                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
10426                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
10427                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
10428                 c2[3] = c[3];
10429         }
10430 }
10431
10432 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
10433 {
10434         int i;
10435         const float *c;
10436         float *c2;
10437         if (!rsurface.passcolor4f)
10438                 return;
10439         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10440         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10441         rsurface.passcolor4f_vertexbuffer = 0;
10442         rsurface.passcolor4f_bufferoffset = 0;
10443         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10444         {
10445                 c2[0] = c[0] * r;
10446                 c2[1] = c[1] * g;
10447                 c2[2] = c[2] * b;
10448                 c2[3] = c[3] * a;
10449         }
10450 }
10451
10452 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
10453 {
10454         int i;
10455         const float *c;
10456         float *c2;
10457         if (!rsurface.passcolor4f)
10458                 return;
10459         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
10460         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10461         rsurface.passcolor4f_vertexbuffer = 0;
10462         rsurface.passcolor4f_bufferoffset = 0;
10463         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
10464         {
10465                 c2[0] = c[0] + r_refdef.scene.ambient;
10466                 c2[1] = c[1] + r_refdef.scene.ambient;
10467                 c2[2] = c[2] + r_refdef.scene.ambient;
10468                 c2[3] = c[3];
10469         }
10470 }
10471
10472 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10473 {
10474         // TODO: optimize
10475         rsurface.passcolor4f = NULL;
10476         rsurface.passcolor4f_vertexbuffer = 0;
10477         rsurface.passcolor4f_bufferoffset = 0;
10478         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10479         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10480         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10481         GL_Color(r, g, b, a);
10482         R_Mesh_TexBind(0, rsurface.lightmaptexture);
10483         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10484         R_Mesh_TexMatrix(0, NULL);
10485         RSurf_DrawBatch();
10486 }
10487
10488 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10489 {
10490         // TODO: optimize applyfog && applycolor case
10491         // just apply fog if necessary, and tint the fog color array if necessary
10492         rsurface.passcolor4f = NULL;
10493         rsurface.passcolor4f_vertexbuffer = 0;
10494         rsurface.passcolor4f_bufferoffset = 0;
10495         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10496         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10497         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10498         GL_Color(r, g, b, a);
10499         RSurf_DrawBatch();
10500 }
10501
10502 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10503 {
10504         // TODO: optimize
10505         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10506         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10507         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10508         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10509         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10510         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10511         GL_Color(r, g, b, a);
10512         RSurf_DrawBatch();
10513 }
10514
10515 static void RSurf_DrawBatch_GL11_ClampColor(void)
10516 {
10517         int i;
10518         const float *c1;
10519         float *c2;
10520         if (!rsurface.passcolor4f)
10521                 return;
10522         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
10523         {
10524                 c2[0] = bound(0.0f, c1[0], 1.0f);
10525                 c2[1] = bound(0.0f, c1[1], 1.0f);
10526                 c2[2] = bound(0.0f, c1[2], 1.0f);
10527                 c2[3] = bound(0.0f, c1[3], 1.0f);
10528         }
10529 }
10530
10531 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
10532 {
10533         int i;
10534         float f;
10535         const float *v;
10536         const float *n;
10537         float *c;
10538         //vec3_t eyedir;
10539
10540         // fake shading
10541         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10542         rsurface.passcolor4f_vertexbuffer = 0;
10543         rsurface.passcolor4f_bufferoffset = 0;
10544         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)
10545         {
10546                 f = -DotProduct(r_refdef.view.forward, n);
10547                 f = max(0, f);
10548                 f = f * 0.85 + 0.15; // work around so stuff won't get black
10549                 f *= r_refdef.lightmapintensity;
10550                 Vector4Set(c, f, f, f, 1);
10551         }
10552 }
10553
10554 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10555 {
10556         RSurf_DrawBatch_GL11_ApplyFakeLight();
10557         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10558         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10559         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10560         GL_Color(r, g, b, a);
10561         RSurf_DrawBatch();
10562 }
10563
10564 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
10565 {
10566         int i;
10567         float f;
10568         float alpha;
10569         const float *v;
10570         const float *n;
10571         float *c;
10572         vec3_t ambientcolor;
10573         vec3_t diffusecolor;
10574         vec3_t lightdir;
10575         // TODO: optimize
10576         // model lighting
10577         VectorCopy(rsurface.modellight_lightdir, lightdir);
10578         f = 0.5f * r_refdef.lightmapintensity;
10579         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
10580         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
10581         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
10582         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
10583         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
10584         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
10585         alpha = *a;
10586         if (VectorLength2(diffusecolor) > 0)
10587         {
10588                 // q3-style directional shading
10589                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10590                 rsurface.passcolor4f_vertexbuffer = 0;
10591                 rsurface.passcolor4f_bufferoffset = 0;
10592                 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)
10593                 {
10594                         if ((f = DotProduct(n, lightdir)) > 0)
10595                                 VectorMA(ambientcolor, f, diffusecolor, c);
10596                         else
10597                                 VectorCopy(ambientcolor, c);
10598                         c[3] = alpha;
10599                 }
10600                 *r = 1;
10601                 *g = 1;
10602                 *b = 1;
10603                 *a = 1;
10604                 *applycolor = false;
10605         }
10606         else
10607         {
10608                 *r = ambientcolor[0];
10609                 *g = ambientcolor[1];
10610                 *b = ambientcolor[2];
10611                 rsurface.passcolor4f = NULL;
10612                 rsurface.passcolor4f_vertexbuffer = 0;
10613                 rsurface.passcolor4f_bufferoffset = 0;
10614         }
10615 }
10616
10617 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
10618 {
10619         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
10620         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
10621         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
10622         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
10623         GL_Color(r, g, b, a);
10624         RSurf_DrawBatch();
10625 }
10626
10627 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10628 {
10629         int i;
10630         float f;
10631         const float *v;
10632         float *c;
10633
10634         // fake shading
10635         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10636         rsurface.passcolor4f_vertexbuffer = 0;
10637         rsurface.passcolor4f_bufferoffset = 0;
10638
10639         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10640         {
10641                 f = 1 - RSurf_FogVertex(v);
10642                 c[0] = r;
10643                 c[1] = g;
10644                 c[2] = b;
10645                 c[3] = f * a;
10646         }
10647 }
10648
10649 void RSurf_SetupDepthAndCulling(void)
10650 {
10651         // submodels are biased to avoid z-fighting with world surfaces that they
10652         // may be exactly overlapping (avoids z-fighting artifacts on certain
10653         // doors and things in Quake maps)
10654         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10655         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10656         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10657         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10658 }
10659
10660 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10661 {
10662         // transparent sky would be ridiculous
10663         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10664                 return;
10665         R_SetupShader_Generic_NoTexture(false, false);
10666         skyrenderlater = true;
10667         RSurf_SetupDepthAndCulling();
10668         GL_DepthMask(true);
10669         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10670         // skymasking on them, and Quake3 never did sky masking (unlike
10671         // software Quake and software Quake2), so disable the sky masking
10672         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10673         // and skymasking also looks very bad when noclipping outside the
10674         // level, so don't use it then either.
10675         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.skymasking && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10676         {
10677                 R_Mesh_ResetTextureState();
10678                 if (skyrendermasked)
10679                 {
10680                         R_SetupShader_DepthOrShadow(false, false, false);
10681                         // depth-only (masking)
10682                         GL_ColorMask(0,0,0,0);
10683                         // just to make sure that braindead drivers don't draw
10684                         // anything despite that colormask...
10685                         GL_BlendFunc(GL_ZERO, GL_ONE);
10686                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10687                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10688                 }
10689                 else
10690                 {
10691                         R_SetupShader_Generic_NoTexture(false, false);
10692                         // fog sky
10693                         GL_BlendFunc(GL_ONE, GL_ZERO);
10694                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10695                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10696                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10697                 }
10698                 RSurf_DrawBatch();
10699                 if (skyrendermasked)
10700                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10701         }
10702         R_Mesh_ResetTextureState();
10703         GL_Color(1, 1, 1, 1);
10704 }
10705
10706 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10707 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10708 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10709 {
10710         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10711                 return;
10712         if (prepass)
10713         {
10714                 // render screenspace normalmap to texture
10715                 GL_DepthMask(true);
10716                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10717                 RSurf_DrawBatch();
10718                 return;
10719         }
10720
10721         // bind lightmap texture
10722
10723         // water/refraction/reflection/camera surfaces have to be handled specially
10724         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10725         {
10726                 int start, end, startplaneindex;
10727                 for (start = 0;start < texturenumsurfaces;start = end)
10728                 {
10729                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10730                         if(startplaneindex < 0)
10731                         {
10732                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10733                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10734                                 end = start + 1;
10735                                 continue;
10736                         }
10737                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10738                                 ;
10739                         // now that we have a batch using the same planeindex, render it
10740                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10741                         {
10742                                 // render water or distortion background
10743                                 GL_DepthMask(true);
10744                                 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);
10745                                 RSurf_DrawBatch();
10746                                 // blend surface on top
10747                                 GL_DepthMask(false);
10748                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10749                                 RSurf_DrawBatch();
10750                         }
10751                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10752                         {
10753                                 // render surface with reflection texture as input
10754                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10755                                 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);
10756                                 RSurf_DrawBatch();
10757                         }
10758                 }
10759                 return;
10760         }
10761
10762         // render surface batch normally
10763         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10764         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);
10765         RSurf_DrawBatch();
10766 }
10767
10768 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10769 {
10770         // OpenGL 1.3 path - anything not completely ancient
10771         qboolean applycolor;
10772         qboolean applyfog;
10773         int layerindex;
10774         const texturelayer_t *layer;
10775         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);
10776         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10777
10778         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10779         {
10780                 vec4_t layercolor;
10781                 int layertexrgbscale;
10782                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10783                 {
10784                         if (layerindex == 0)
10785                                 GL_AlphaTest(true);
10786                         else
10787                         {
10788                                 GL_AlphaTest(false);
10789                                 GL_DepthFunc(GL_EQUAL);
10790                         }
10791                 }
10792                 GL_DepthMask(layer->depthmask && writedepth);
10793                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10794                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10795                 {
10796                         layertexrgbscale = 4;
10797                         VectorScale(layer->color, 0.25f, layercolor);
10798                 }
10799                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10800                 {
10801                         layertexrgbscale = 2;
10802                         VectorScale(layer->color, 0.5f, layercolor);
10803                 }
10804                 else
10805                 {
10806                         layertexrgbscale = 1;
10807                         VectorScale(layer->color, 1.0f, layercolor);
10808                 }
10809                 layercolor[3] = layer->color[3];
10810                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10811                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10812                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10813                 switch (layer->type)
10814                 {
10815                 case TEXTURELAYERTYPE_LITTEXTURE:
10816                         // single-pass lightmapped texture with 2x rgbscale
10817                         R_Mesh_TexBind(0, r_texture_white);
10818                         R_Mesh_TexMatrix(0, NULL);
10819                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10820                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10821                         R_Mesh_TexBind(1, layer->texture);
10822                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10823                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10824                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10825                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10826                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10827                         else if (FAKELIGHT_ENABLED)
10828                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10829                         else if (rsurface.uselightmaptexture)
10830                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10831                         else
10832                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10833                         break;
10834                 case TEXTURELAYERTYPE_TEXTURE:
10835                         // singletexture unlit texture with transparency support
10836                         R_Mesh_TexBind(0, layer->texture);
10837                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10838                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10839                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10840                         R_Mesh_TexBind(1, 0);
10841                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10842                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10843                         break;
10844                 case TEXTURELAYERTYPE_FOG:
10845                         // singletexture fogging
10846                         if (layer->texture)
10847                         {
10848                                 R_Mesh_TexBind(0, layer->texture);
10849                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10850                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10851                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10852                         }
10853                         else
10854                         {
10855                                 R_Mesh_TexBind(0, 0);
10856                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10857                         }
10858                         R_Mesh_TexBind(1, 0);
10859                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10860                         // generate a color array for the fog pass
10861                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10862                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10863                         RSurf_DrawBatch();
10864                         break;
10865                 default:
10866                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10867                 }
10868         }
10869         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10870         {
10871                 GL_DepthFunc(GL_LEQUAL);
10872                 GL_AlphaTest(false);
10873         }
10874 }
10875
10876 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10877 {
10878         // OpenGL 1.1 - crusty old voodoo path
10879         qboolean applyfog;
10880         int layerindex;
10881         const texturelayer_t *layer;
10882         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);
10883         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10884
10885         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10886         {
10887                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10888                 {
10889                         if (layerindex == 0)
10890                                 GL_AlphaTest(true);
10891                         else
10892                         {
10893                                 GL_AlphaTest(false);
10894                                 GL_DepthFunc(GL_EQUAL);
10895                         }
10896                 }
10897                 GL_DepthMask(layer->depthmask && writedepth);
10898                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10899                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10900                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10901                 switch (layer->type)
10902                 {
10903                 case TEXTURELAYERTYPE_LITTEXTURE:
10904                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10905                         {
10906                                 // two-pass lit texture with 2x rgbscale
10907                                 // first the lightmap pass
10908                                 R_Mesh_TexBind(0, r_texture_white);
10909                                 R_Mesh_TexMatrix(0, NULL);
10910                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10911                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10912                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10913                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10914                                 else if (FAKELIGHT_ENABLED)
10915                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10916                                 else if (rsurface.uselightmaptexture)
10917                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10918                                 else
10919                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10920                                 // then apply the texture to it
10921                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10922                                 R_Mesh_TexBind(0, layer->texture);
10923                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10924                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10925                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10926                                 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);
10927                         }
10928                         else
10929                         {
10930                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10931                                 R_Mesh_TexBind(0, layer->texture);
10932                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10933                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10934                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10935                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10936                                         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);
10937                                 else if (FAKELIGHT_ENABLED)
10938                                         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);
10939                                 else
10940                                         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);
10941                         }
10942                         break;
10943                 case TEXTURELAYERTYPE_TEXTURE:
10944                         // singletexture unlit texture with transparency support
10945                         R_Mesh_TexBind(0, layer->texture);
10946                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10947                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10948                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10949                         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);
10950                         break;
10951                 case TEXTURELAYERTYPE_FOG:
10952                         // singletexture fogging
10953                         if (layer->texture)
10954                         {
10955                                 R_Mesh_TexBind(0, layer->texture);
10956                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10957                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10958                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10959                         }
10960                         else
10961                         {
10962                                 R_Mesh_TexBind(0, 0);
10963                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10964                         }
10965                         // generate a color array for the fog pass
10966                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10967                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10968                         RSurf_DrawBatch();
10969                         break;
10970                 default:
10971                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10972                 }
10973         }
10974         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10975         {
10976                 GL_DepthFunc(GL_LEQUAL);
10977                 GL_AlphaTest(false);
10978         }
10979 }
10980
10981 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10982 {
10983         int vi;
10984         int j;
10985         r_vertexgeneric_t *batchvertex;
10986         float c[4];
10987
10988 //      R_Mesh_ResetTextureState();
10989         R_SetupShader_Generic_NoTexture(false, false);
10990
10991         if(rsurface.texture && rsurface.texture->currentskinframe)
10992         {
10993                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10994                 c[3] *= rsurface.texture->currentalpha;
10995         }
10996         else
10997         {
10998                 c[0] = 1;
10999                 c[1] = 0;
11000                 c[2] = 1;
11001                 c[3] = 1;
11002         }
11003
11004         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
11005         {
11006                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
11007                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
11008                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
11009         }
11010
11011         // brighten it up (as texture value 127 means "unlit")
11012         c[0] *= 2 * r_refdef.view.colorscale;
11013         c[1] *= 2 * r_refdef.view.colorscale;
11014         c[2] *= 2 * r_refdef.view.colorscale;
11015
11016         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
11017                 c[3] *= r_wateralpha.value;
11018
11019         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
11020         {
11021                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11022                 GL_DepthMask(false);
11023         }
11024         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
11025         {
11026                 GL_BlendFunc(GL_ONE, GL_ONE);
11027                 GL_DepthMask(false);
11028         }
11029         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
11030         {
11031                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
11032                 GL_DepthMask(false);
11033         }
11034         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
11035         {
11036                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
11037                 GL_DepthMask(false);
11038         }
11039         else
11040         {
11041                 GL_BlendFunc(GL_ONE, GL_ZERO);
11042                 GL_DepthMask(writedepth);
11043         }
11044
11045         if (r_showsurfaces.integer == 3)
11046         {
11047                 rsurface.passcolor4f = NULL;
11048
11049                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
11050                 {
11051                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11052
11053                         rsurface.passcolor4f = NULL;
11054                         rsurface.passcolor4f_vertexbuffer = 0;
11055                         rsurface.passcolor4f_bufferoffset = 0;
11056                 }
11057                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
11058                 {
11059                         qboolean applycolor = true;
11060                         float one = 1.0;
11061
11062                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11063
11064                         r_refdef.lightmapintensity = 1;
11065                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
11066                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11067                 }
11068                 else if (FAKELIGHT_ENABLED)
11069                 {
11070                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11071
11072                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
11073                         RSurf_DrawBatch_GL11_ApplyFakeLight();
11074                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
11075                 }
11076                 else
11077                 {
11078                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11079
11080                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
11081                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
11082                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
11083                 }
11084
11085                 if(!rsurface.passcolor4f)
11086                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
11087
11088                 RSurf_DrawBatch_GL11_ApplyAmbient();
11089                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
11090                 if(r_refdef.fogenabled)
11091                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
11092                 RSurf_DrawBatch_GL11_ClampColor();
11093
11094                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
11095                 R_SetupShader_Generic_NoTexture(false, false);
11096                 RSurf_DrawBatch();
11097         }
11098         else if (!r_refdef.view.showdebug)
11099         {
11100                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11101                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11102                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11103                 {
11104                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11105                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
11106                 }
11107                 R_Mesh_PrepareVertices_Generic_Unlock();
11108                 RSurf_DrawBatch();
11109         }
11110         else if (r_showsurfaces.integer == 4)
11111         {
11112                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11113                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
11114                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
11115                 {
11116                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
11117                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11118                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
11119                 }
11120                 R_Mesh_PrepareVertices_Generic_Unlock();
11121                 RSurf_DrawBatch();
11122         }
11123         else if (r_showsurfaces.integer == 2)
11124         {
11125                 const int *e;
11126                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11127                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
11128                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
11129                 {
11130                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
11131                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
11132                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
11133                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
11134                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
11135                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
11136                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
11137                 }
11138                 R_Mesh_PrepareVertices_Generic_Unlock();
11139                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
11140         }
11141         else
11142         {
11143                 int texturesurfaceindex;
11144                 int k;
11145                 const msurface_t *surface;
11146                 float surfacecolor4f[4];
11147                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
11148                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
11149                 vi = 0;
11150                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
11151                 {
11152                         surface = texturesurfacelist[texturesurfaceindex];
11153                         k = (int)(((size_t)surface) / sizeof(msurface_t));
11154                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
11155                         for (j = 0;j < surface->num_vertices;j++)
11156                         {
11157                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
11158                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
11159                                 vi++;
11160                         }
11161                 }
11162                 R_Mesh_PrepareVertices_Generic_Unlock();
11163                 RSurf_DrawBatch();
11164         }
11165 }
11166
11167 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11168 {
11169         CHECKGLERROR
11170         RSurf_SetupDepthAndCulling();
11171         if (r_showsurfaces.integer)
11172         {
11173                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11174                 return;
11175         }
11176         switch (vid.renderpath)
11177         {
11178         case RENDERPATH_GL20:
11179         case RENDERPATH_D3D9:
11180         case RENDERPATH_D3D10:
11181         case RENDERPATH_D3D11:
11182         case RENDERPATH_SOFT:
11183         case RENDERPATH_GLES2:
11184                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11185                 break;
11186         case RENDERPATH_GL13:
11187         case RENDERPATH_GLES1:
11188                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11189                 break;
11190         case RENDERPATH_GL11:
11191                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11192                 break;
11193         }
11194         CHECKGLERROR
11195 }
11196
11197 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
11198 {
11199         CHECKGLERROR
11200         RSurf_SetupDepthAndCulling();
11201         if (r_showsurfaces.integer)
11202         {
11203                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
11204                 return;
11205         }
11206         switch (vid.renderpath)
11207         {
11208         case RENDERPATH_GL20:
11209         case RENDERPATH_D3D9:
11210         case RENDERPATH_D3D10:
11211         case RENDERPATH_D3D11:
11212         case RENDERPATH_SOFT:
11213         case RENDERPATH_GLES2:
11214                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11215                 break;
11216         case RENDERPATH_GL13:
11217         case RENDERPATH_GLES1:
11218                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
11219                 break;
11220         case RENDERPATH_GL11:
11221                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
11222                 break;
11223         }
11224         CHECKGLERROR
11225 }
11226
11227 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11228 {
11229         int i, j;
11230         int texturenumsurfaces, endsurface;
11231         texture_t *texture;
11232         const msurface_t *surface;
11233         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
11234
11235         // if the model is static it doesn't matter what value we give for
11236         // wantnormals and wanttangents, so this logic uses only rules applicable
11237         // to a model, knowing that they are meaningless otherwise
11238         if (ent == r_refdef.scene.worldentity)
11239                 RSurf_ActiveWorldEntity();
11240         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11241                 RSurf_ActiveModelEntity(ent, false, false, false);
11242         else
11243         {
11244                 switch (vid.renderpath)
11245                 {
11246                 case RENDERPATH_GL20:
11247                 case RENDERPATH_D3D9:
11248                 case RENDERPATH_D3D10:
11249                 case RENDERPATH_D3D11:
11250                 case RENDERPATH_SOFT:
11251                 case RENDERPATH_GLES2:
11252                         RSurf_ActiveModelEntity(ent, true, true, false);
11253                         break;
11254                 case RENDERPATH_GL11:
11255                 case RENDERPATH_GL13:
11256                 case RENDERPATH_GLES1:
11257                         RSurf_ActiveModelEntity(ent, true, false, false);
11258                         break;
11259                 }
11260         }
11261
11262         if (r_transparentdepthmasking.integer)
11263         {
11264                 qboolean setup = false;
11265                 for (i = 0;i < numsurfaces;i = j)
11266                 {
11267                         j = i + 1;
11268                         surface = rsurface.modelsurfaces + surfacelist[i];
11269                         texture = surface->texture;
11270                         rsurface.texture = R_GetCurrentTexture(texture);
11271                         rsurface.lightmaptexture = NULL;
11272                         rsurface.deluxemaptexture = NULL;
11273                         rsurface.uselightmaptexture = false;
11274                         // scan ahead until we find a different texture
11275                         endsurface = min(i + 1024, numsurfaces);
11276                         texturenumsurfaces = 0;
11277                         texturesurfacelist[texturenumsurfaces++] = surface;
11278                         for (;j < endsurface;j++)
11279                         {
11280                                 surface = rsurface.modelsurfaces + surfacelist[j];
11281                                 if (texture != surface->texture)
11282                                         break;
11283                                 texturesurfacelist[texturenumsurfaces++] = surface;
11284                         }
11285                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
11286                                 continue;
11287                         // render the range of surfaces as depth
11288                         if (!setup)
11289                         {
11290                                 setup = true;
11291                                 GL_ColorMask(0,0,0,0);
11292                                 GL_Color(1,1,1,1);
11293                                 GL_DepthTest(true);
11294                                 GL_BlendFunc(GL_ONE, GL_ZERO);
11295                                 GL_DepthMask(true);
11296 //                              R_Mesh_ResetTextureState();
11297                         }
11298                         RSurf_SetupDepthAndCulling();
11299                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11300                         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11301                         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11302                         RSurf_DrawBatch();
11303                 }
11304                 if (setup)
11305                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
11306         }
11307
11308         for (i = 0;i < numsurfaces;i = j)
11309         {
11310                 j = i + 1;
11311                 surface = rsurface.modelsurfaces + surfacelist[i];
11312                 texture = surface->texture;
11313                 rsurface.texture = R_GetCurrentTexture(texture);
11314                 // scan ahead until we find a different texture
11315                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
11316                 texturenumsurfaces = 0;
11317                 texturesurfacelist[texturenumsurfaces++] = surface;
11318                 if(FAKELIGHT_ENABLED)
11319                 {
11320                         rsurface.lightmaptexture = NULL;
11321                         rsurface.deluxemaptexture = NULL;
11322                         rsurface.uselightmaptexture = false;
11323                         for (;j < endsurface;j++)
11324                         {
11325                                 surface = rsurface.modelsurfaces + surfacelist[j];
11326                                 if (texture != surface->texture)
11327                                         break;
11328                                 texturesurfacelist[texturenumsurfaces++] = surface;
11329                         }
11330                 }
11331                 else
11332                 {
11333                         rsurface.lightmaptexture = surface->lightmaptexture;
11334                         rsurface.deluxemaptexture = surface->deluxemaptexture;
11335                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
11336                         for (;j < endsurface;j++)
11337                         {
11338                                 surface = rsurface.modelsurfaces + surfacelist[j];
11339                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
11340                                         break;
11341                                 texturesurfacelist[texturenumsurfaces++] = surface;
11342                         }
11343                 }
11344                 // render the range of surfaces
11345                 if (ent == r_refdef.scene.worldentity)
11346                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11347                 else
11348                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
11349         }
11350         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11351 }
11352
11353 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11354 {
11355         // transparent surfaces get pushed off into the transparent queue
11356         int surfacelistindex;
11357         const msurface_t *surface;
11358         vec3_t tempcenter, center;
11359         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
11360         {
11361                 surface = texturesurfacelist[surfacelistindex];
11362                 if (r_transparent_sortsurfacesbynearest.integer)
11363                 {
11364                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
11365                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
11366                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
11367                 }
11368                 else
11369                 {
11370                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
11371                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
11372                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
11373                 }
11374                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
11375                 if (rsurface.entity->transparent_offset) // transparent offset
11376                 {
11377                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
11378                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
11379                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
11380                 }
11381                 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);
11382         }
11383 }
11384
11385 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
11386 {
11387         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
11388                 return;
11389         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
11390                 return;
11391         RSurf_SetupDepthAndCulling();
11392         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
11393         R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
11394         R_SetupShader_DepthOrShadow(false, false, !!rsurface.batchskeletaltransform3x4);
11395         RSurf_DrawBatch();
11396 }
11397
11398 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11399 {
11400         CHECKGLERROR
11401         if (depthonly)
11402                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11403         else if (prepass)
11404         {
11405                 if (!rsurface.texture->currentnumlayers)
11406                         return;
11407                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11408                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11409                 else
11410                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11411         }
11412         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11413                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11414         else if (!rsurface.texture->currentnumlayers)
11415                 return;
11416         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11417         {
11418                 // in the deferred case, transparent surfaces were queued during prepass
11419                 if (!r_shadow_usingdeferredprepass)
11420                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11421         }
11422         else
11423         {
11424                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11425                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11426         }
11427         CHECKGLERROR
11428 }
11429
11430 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11431 {
11432         int i, j;
11433         texture_t *texture;
11434         R_FrameData_SetMark();
11435         // break the surface list down into batches by texture and use of lightmapping
11436         for (i = 0;i < numsurfaces;i = j)
11437         {
11438                 j = i + 1;
11439                 // texture is the base texture pointer, rsurface.texture is the
11440                 // current frame/skin the texture is directing us to use (for example
11441                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11442                 // use skin 1 instead)
11443                 texture = surfacelist[i]->texture;
11444                 rsurface.texture = R_GetCurrentTexture(texture);
11445                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11446                 {
11447                         // if this texture is not the kind we want, skip ahead to the next one
11448                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11449                                 ;
11450                         continue;
11451                 }
11452                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11453                 {
11454                         rsurface.lightmaptexture = NULL;
11455                         rsurface.deluxemaptexture = NULL;
11456                         rsurface.uselightmaptexture = false;
11457                         // simply scan ahead until we find a different texture or lightmap state
11458                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11459                                 ;
11460                 }
11461                 else
11462                 {
11463                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11464                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11465                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11466                         // simply scan ahead until we find a different texture or lightmap state
11467                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11468                                 ;
11469                 }
11470                 // render the range of surfaces
11471                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11472         }
11473         R_FrameData_ReturnToMark();
11474 }
11475
11476 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
11477 {
11478         CHECKGLERROR
11479         if (depthonly)
11480                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
11481         else if (prepass)
11482         {
11483                 if (!rsurface.texture->currentnumlayers)
11484                         return;
11485                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
11486                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11487                 else
11488                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
11489         }
11490         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
11491                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
11492         else if (!rsurface.texture->currentnumlayers)
11493                 return;
11494         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
11495         {
11496                 // in the deferred case, transparent surfaces were queued during prepass
11497                 if (!r_shadow_usingdeferredprepass)
11498                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
11499         }
11500         else
11501         {
11502                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
11503                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
11504         }
11505         CHECKGLERROR
11506 }
11507
11508 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
11509 {
11510         int i, j;
11511         texture_t *texture;
11512         R_FrameData_SetMark();
11513         // break the surface list down into batches by texture and use of lightmapping
11514         for (i = 0;i < numsurfaces;i = j)
11515         {
11516                 j = i + 1;
11517                 // texture is the base texture pointer, rsurface.texture is the
11518                 // current frame/skin the texture is directing us to use (for example
11519                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
11520                 // use skin 1 instead)
11521                 texture = surfacelist[i]->texture;
11522                 rsurface.texture = R_GetCurrentTexture(texture);
11523                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
11524                 {
11525                         // if this texture is not the kind we want, skip ahead to the next one
11526                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11527                                 ;
11528                         continue;
11529                 }
11530                 if(FAKELIGHT_ENABLED || depthonly || prepass)
11531                 {
11532                         rsurface.lightmaptexture = NULL;
11533                         rsurface.deluxemaptexture = NULL;
11534                         rsurface.uselightmaptexture = false;
11535                         // simply scan ahead until we find a different texture or lightmap state
11536                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
11537                                 ;
11538                 }
11539                 else
11540                 {
11541                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
11542                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
11543                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
11544                         // simply scan ahead until we find a different texture or lightmap state
11545                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
11546                                 ;
11547                 }
11548                 // render the range of surfaces
11549                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
11550         }
11551         R_FrameData_ReturnToMark();
11552 }
11553
11554 float locboxvertex3f[6*4*3] =
11555 {
11556         1,0,1, 1,0,0, 1,1,0, 1,1,1,
11557         0,1,1, 0,1,0, 0,0,0, 0,0,1,
11558         1,1,1, 1,1,0, 0,1,0, 0,1,1,
11559         0,0,1, 0,0,0, 1,0,0, 1,0,1,
11560         0,0,1, 1,0,1, 1,1,1, 0,1,1,
11561         1,0,0, 0,0,0, 0,1,0, 1,1,0
11562 };
11563
11564 unsigned short locboxelements[6*2*3] =
11565 {
11566          0, 1, 2, 0, 2, 3,
11567          4, 5, 6, 4, 6, 7,
11568          8, 9,10, 8,10,11,
11569         12,13,14, 12,14,15,
11570         16,17,18, 16,18,19,
11571         20,21,22, 20,22,23
11572 };
11573
11574 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
11575 {
11576         int i, j;
11577         cl_locnode_t *loc = (cl_locnode_t *)ent;
11578         vec3_t mins, size;
11579         float vertex3f[6*4*3];
11580         CHECKGLERROR
11581         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11582         GL_DepthMask(false);
11583         GL_DepthRange(0, 1);
11584         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11585         GL_DepthTest(true);
11586         GL_CullFace(GL_NONE);
11587         R_EntityMatrix(&identitymatrix);
11588
11589 //      R_Mesh_ResetTextureState();
11590
11591         i = surfacelist[0];
11592         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11593                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11594                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
11595                         surfacelist[0] < 0 ? 0.5f : 0.125f);
11596
11597         if (VectorCompare(loc->mins, loc->maxs))
11598         {
11599                 VectorSet(size, 2, 2, 2);
11600                 VectorMA(loc->mins, -0.5f, size, mins);
11601         }
11602         else
11603         {
11604                 VectorCopy(loc->mins, mins);
11605                 VectorSubtract(loc->maxs, loc->mins, size);
11606         }
11607
11608         for (i = 0;i < 6*4*3;)
11609                 for (j = 0;j < 3;j++, i++)
11610                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
11611
11612         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
11613         R_SetupShader_Generic_NoTexture(false, false);
11614         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
11615 }
11616
11617 void R_DrawLocs(void)
11618 {
11619         int index;
11620         cl_locnode_t *loc, *nearestloc;
11621         vec3_t center;
11622         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11623         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11624         {
11625                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11626                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11627         }
11628 }
11629
11630 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11631 {
11632         if (decalsystem->decals)
11633                 Mem_Free(decalsystem->decals);
11634         memset(decalsystem, 0, sizeof(*decalsystem));
11635 }
11636
11637 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)
11638 {
11639         tridecal_t *decal;
11640         tridecal_t *decals;
11641         int i;
11642
11643         // expand or initialize the system
11644         if (decalsystem->maxdecals <= decalsystem->numdecals)
11645         {
11646                 decalsystem_t old = *decalsystem;
11647                 qboolean useshortelements;
11648                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11649                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11650                 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)));
11651                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11652                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11653                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11654                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11655                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11656                 if (decalsystem->numdecals)
11657                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11658                 if (old.decals)
11659                         Mem_Free(old.decals);
11660                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11661                         decalsystem->element3i[i] = i;
11662                 if (useshortelements)
11663                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11664                                 decalsystem->element3s[i] = i;
11665         }
11666
11667         // grab a decal and search for another free slot for the next one
11668         decals = decalsystem->decals;
11669         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11670         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11671                 ;
11672         decalsystem->freedecal = i;
11673         if (decalsystem->numdecals <= i)
11674                 decalsystem->numdecals = i + 1;
11675
11676         // initialize the decal
11677         decal->lived = 0;
11678         decal->triangleindex = triangleindex;
11679         decal->surfaceindex = surfaceindex;
11680         decal->decalsequence = decalsequence;
11681         decal->color4f[0][0] = c0[0];
11682         decal->color4f[0][1] = c0[1];
11683         decal->color4f[0][2] = c0[2];
11684         decal->color4f[0][3] = 1;
11685         decal->color4f[1][0] = c1[0];
11686         decal->color4f[1][1] = c1[1];
11687         decal->color4f[1][2] = c1[2];
11688         decal->color4f[1][3] = 1;
11689         decal->color4f[2][0] = c2[0];
11690         decal->color4f[2][1] = c2[1];
11691         decal->color4f[2][2] = c2[2];
11692         decal->color4f[2][3] = 1;
11693         decal->vertex3f[0][0] = v0[0];
11694         decal->vertex3f[0][1] = v0[1];
11695         decal->vertex3f[0][2] = v0[2];
11696         decal->vertex3f[1][0] = v1[0];
11697         decal->vertex3f[1][1] = v1[1];
11698         decal->vertex3f[1][2] = v1[2];
11699         decal->vertex3f[2][0] = v2[0];
11700         decal->vertex3f[2][1] = v2[1];
11701         decal->vertex3f[2][2] = v2[2];
11702         decal->texcoord2f[0][0] = t0[0];
11703         decal->texcoord2f[0][1] = t0[1];
11704         decal->texcoord2f[1][0] = t1[0];
11705         decal->texcoord2f[1][1] = t1[1];
11706         decal->texcoord2f[2][0] = t2[0];
11707         decal->texcoord2f[2][1] = t2[1];
11708         TriangleNormal(v0, v1, v2, decal->plane);
11709         VectorNormalize(decal->plane);
11710         decal->plane[3] = DotProduct(v0, decal->plane);
11711 }
11712
11713 extern cvar_t cl_decals_bias;
11714 extern cvar_t cl_decals_models;
11715 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11716 // baseparms, parms, temps
11717 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)
11718 {
11719         int cornerindex;
11720         int index;
11721         float v[9][3];
11722         const float *vertex3f;
11723         const float *normal3f;
11724         int numpoints;
11725         float points[2][9][3];
11726         float temp[3];
11727         float tc[9][2];
11728         float f;
11729         float c[9][4];
11730         const int *e;
11731
11732         e = rsurface.modelelement3i + 3*triangleindex;
11733
11734         vertex3f = rsurface.modelvertex3f;
11735         normal3f = rsurface.modelnormal3f;
11736
11737         if (normal3f)
11738         {
11739                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11740                 {
11741                         index = 3*e[cornerindex];
11742                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11743                 }
11744         }
11745         else
11746         {
11747                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11748                 {
11749                         index = 3*e[cornerindex];
11750                         VectorCopy(vertex3f + index, v[cornerindex]);
11751                 }
11752         }
11753
11754         // cull backfaces
11755         //TriangleNormal(v[0], v[1], v[2], normal);
11756         //if (DotProduct(normal, localnormal) < 0.0f)
11757         //      continue;
11758         // clip by each of the box planes formed from the projection matrix
11759         // if anything survives, we emit the decal
11760         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]);
11761         if (numpoints < 3)
11762                 return;
11763         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]);
11764         if (numpoints < 3)
11765                 return;
11766         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]);
11767         if (numpoints < 3)
11768                 return;
11769         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]);
11770         if (numpoints < 3)
11771                 return;
11772         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]);
11773         if (numpoints < 3)
11774                 return;
11775         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]);
11776         if (numpoints < 3)
11777                 return;
11778         // some part of the triangle survived, so we have to accept it...
11779         if (dynamic)
11780         {
11781                 // dynamic always uses the original triangle
11782                 numpoints = 3;
11783                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11784                 {
11785                         index = 3*e[cornerindex];
11786                         VectorCopy(vertex3f + index, v[cornerindex]);
11787                 }
11788         }
11789         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11790         {
11791                 // convert vertex positions to texcoords
11792                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11793                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11794                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11795                 // calculate distance fade from the projection origin
11796                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11797                 f = bound(0.0f, f, 1.0f);
11798                 c[cornerindex][0] = r * f;
11799                 c[cornerindex][1] = g * f;
11800                 c[cornerindex][2] = b * f;
11801                 c[cornerindex][3] = 1.0f;
11802                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11803         }
11804         if (dynamic)
11805                 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);
11806         else
11807                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11808                         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);
11809 }
11810 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)
11811 {
11812         matrix4x4_t projection;
11813         decalsystem_t *decalsystem;
11814         qboolean dynamic;
11815         dp_model_t *model;
11816         const msurface_t *surface;
11817         const msurface_t *surfaces;
11818         const int *surfacelist;
11819         const texture_t *texture;
11820         int numtriangles;
11821         int numsurfacelist;
11822         int surfacelistindex;
11823         int surfaceindex;
11824         int triangleindex;
11825         float localorigin[3];
11826         float localnormal[3];
11827         float localmins[3];
11828         float localmaxs[3];
11829         float localsize;
11830         //float normal[3];
11831         float planes[6][4];
11832         float angles[3];
11833         bih_t *bih;
11834         int bih_triangles_count;
11835         int bih_triangles[256];
11836         int bih_surfaces[256];
11837
11838         decalsystem = &ent->decalsystem;
11839         model = ent->model;
11840         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11841         {
11842                 R_DecalSystem_Reset(&ent->decalsystem);
11843                 return;
11844         }
11845
11846         if (!model->brush.data_leafs && !cl_decals_models.integer)
11847         {
11848                 if (decalsystem->model)
11849                         R_DecalSystem_Reset(decalsystem);
11850                 return;
11851         }
11852
11853         if (decalsystem->model != model)
11854                 R_DecalSystem_Reset(decalsystem);
11855         decalsystem->model = model;
11856
11857         RSurf_ActiveModelEntity(ent, true, false, false);
11858
11859         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11860         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11861         VectorNormalize(localnormal);
11862         localsize = worldsize*rsurface.inversematrixscale;
11863         localmins[0] = localorigin[0] - localsize;
11864         localmins[1] = localorigin[1] - localsize;
11865         localmins[2] = localorigin[2] - localsize;
11866         localmaxs[0] = localorigin[0] + localsize;
11867         localmaxs[1] = localorigin[1] + localsize;
11868         localmaxs[2] = localorigin[2] + localsize;
11869
11870         //VectorCopy(localnormal, planes[4]);
11871         //VectorVectors(planes[4], planes[2], planes[0]);
11872         AnglesFromVectors(angles, localnormal, NULL, false);
11873         AngleVectors(angles, planes[0], planes[2], planes[4]);
11874         VectorNegate(planes[0], planes[1]);
11875         VectorNegate(planes[2], planes[3]);
11876         VectorNegate(planes[4], planes[5]);
11877         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11878         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11879         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11880         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11881         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11882         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11883
11884 #if 1
11885 // works
11886 {
11887         matrix4x4_t forwardprojection;
11888         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11889         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11890 }
11891 #else
11892 // broken
11893 {
11894         float projectionvector[4][3];
11895         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11896         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11897         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11898         projectionvector[0][0] = planes[0][0] * ilocalsize;
11899         projectionvector[0][1] = planes[1][0] * ilocalsize;
11900         projectionvector[0][2] = planes[2][0] * ilocalsize;
11901         projectionvector[1][0] = planes[0][1] * ilocalsize;
11902         projectionvector[1][1] = planes[1][1] * ilocalsize;
11903         projectionvector[1][2] = planes[2][1] * ilocalsize;
11904         projectionvector[2][0] = planes[0][2] * ilocalsize;
11905         projectionvector[2][1] = planes[1][2] * ilocalsize;
11906         projectionvector[2][2] = planes[2][2] * ilocalsize;
11907         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11908         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11909         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11910         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11911 }
11912 #endif
11913
11914         dynamic = model->surfmesh.isanimated;
11915         numsurfacelist = model->nummodelsurfaces;
11916         surfacelist = model->sortedmodelsurfaces;
11917         surfaces = model->data_surfaces;
11918
11919         bih = NULL;
11920         bih_triangles_count = -1;
11921         if(!dynamic)
11922         {
11923                 if(model->render_bih.numleafs)
11924                         bih = &model->render_bih;
11925                 else if(model->collision_bih.numleafs)
11926                         bih = &model->collision_bih;
11927         }
11928         if(bih)
11929                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11930         if(bih_triangles_count == 0)
11931                 return;
11932         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11933                 return;
11934         if(bih_triangles_count > 0)
11935         {
11936                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11937                 {
11938                         surfaceindex = bih_surfaces[triangleindex];
11939                         surface = surfaces + surfaceindex;
11940                         texture = surface->texture;
11941                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11942                                 continue;
11943                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11944                                 continue;
11945                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11946                 }
11947         }
11948         else
11949         {
11950                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11951                 {
11952                         surfaceindex = surfacelist[surfacelistindex];
11953                         surface = surfaces + surfaceindex;
11954                         // check cull box first because it rejects more than any other check
11955                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11956                                 continue;
11957                         // skip transparent surfaces
11958                         texture = surface->texture;
11959                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11960                                 continue;
11961                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11962                                 continue;
11963                         numtriangles = surface->num_triangles;
11964                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11965                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11966                 }
11967         }
11968 }
11969
11970 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11971 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)
11972 {
11973         int renderentityindex;
11974         float worldmins[3];
11975         float worldmaxs[3];
11976         entity_render_t *ent;
11977
11978         if (!cl_decals_newsystem.integer)
11979                 return;
11980
11981         worldmins[0] = worldorigin[0] - worldsize;
11982         worldmins[1] = worldorigin[1] - worldsize;
11983         worldmins[2] = worldorigin[2] - worldsize;
11984         worldmaxs[0] = worldorigin[0] + worldsize;
11985         worldmaxs[1] = worldorigin[1] + worldsize;
11986         worldmaxs[2] = worldorigin[2] + worldsize;
11987
11988         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11989
11990         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11991         {
11992                 ent = r_refdef.scene.entities[renderentityindex];
11993                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11994                         continue;
11995
11996                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11997         }
11998 }
11999
12000 typedef struct r_decalsystem_splatqueue_s
12001 {
12002         vec3_t worldorigin;
12003         vec3_t worldnormal;
12004         float color[4];
12005         float tcrange[4];
12006         float worldsize;
12007         unsigned int decalsequence;
12008 }
12009 r_decalsystem_splatqueue_t;
12010
12011 int r_decalsystem_numqueued = 0;
12012 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
12013
12014 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)
12015 {
12016         r_decalsystem_splatqueue_t *queue;
12017
12018         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
12019                 return;
12020
12021         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
12022         VectorCopy(worldorigin, queue->worldorigin);
12023         VectorCopy(worldnormal, queue->worldnormal);
12024         Vector4Set(queue->color, r, g, b, a);
12025         Vector4Set(queue->tcrange, s1, t1, s2, t2);
12026         queue->worldsize = worldsize;
12027         queue->decalsequence = cl.decalsequence++;
12028 }
12029
12030 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
12031 {
12032         int i;
12033         r_decalsystem_splatqueue_t *queue;
12034
12035         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
12036                 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);
12037         r_decalsystem_numqueued = 0;
12038 }
12039
12040 extern cvar_t cl_decals_max;
12041 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
12042 {
12043         int i;
12044         decalsystem_t *decalsystem = &ent->decalsystem;
12045         int numdecals;
12046         unsigned int killsequence;
12047         tridecal_t *decal;
12048         float frametime;
12049         float lifetime;
12050
12051         if (!decalsystem->numdecals)
12052                 return;
12053
12054         if (r_showsurfaces.integer)
12055                 return;
12056
12057         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12058         {
12059                 R_DecalSystem_Reset(decalsystem);
12060                 return;
12061         }
12062
12063         killsequence = cl.decalsequence - bound(1, (unsigned int) cl_decals_max.integer, cl.decalsequence);
12064         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
12065
12066         if (decalsystem->lastupdatetime)
12067                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
12068         else
12069                 frametime = 0;
12070         decalsystem->lastupdatetime = r_refdef.scene.time;
12071         numdecals = decalsystem->numdecals;
12072
12073         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12074         {
12075                 if (decal->color4f[0][3])
12076                 {
12077                         decal->lived += frametime;
12078                         if (killsequence > decal->decalsequence || decal->lived >= lifetime)
12079                         {
12080                                 memset(decal, 0, sizeof(*decal));
12081                                 if (decalsystem->freedecal > i)
12082                                         decalsystem->freedecal = i;
12083                         }
12084                 }
12085         }
12086         decal = decalsystem->decals;
12087         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
12088                 numdecals--;
12089
12090         // collapse the array by shuffling the tail decals into the gaps
12091         for (;;)
12092         {
12093                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
12094                         decalsystem->freedecal++;
12095                 if (decalsystem->freedecal == numdecals)
12096                         break;
12097                 decal[decalsystem->freedecal] = decal[--numdecals];
12098         }
12099
12100         decalsystem->numdecals = numdecals;
12101
12102         if (numdecals <= 0)
12103         {
12104                 // if there are no decals left, reset decalsystem
12105                 R_DecalSystem_Reset(decalsystem);
12106         }
12107 }
12108
12109 extern skinframe_t *decalskinframe;
12110 static void R_DrawModelDecals_Entity(entity_render_t *ent)
12111 {
12112         int i;
12113         decalsystem_t *decalsystem = &ent->decalsystem;
12114         int numdecals;
12115         tridecal_t *decal;
12116         float faderate;
12117         float alpha;
12118         float *v3f;
12119         float *c4f;
12120         float *t2f;
12121         const int *e;
12122         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
12123         int numtris = 0;
12124
12125         numdecals = decalsystem->numdecals;
12126         if (!numdecals)
12127                 return;
12128
12129         if (r_showsurfaces.integer)
12130                 return;
12131
12132         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
12133         {
12134                 R_DecalSystem_Reset(decalsystem);
12135                 return;
12136         }
12137
12138         // if the model is static it doesn't matter what value we give for
12139         // wantnormals and wanttangents, so this logic uses only rules applicable
12140         // to a model, knowing that they are meaningless otherwise
12141         if (ent == r_refdef.scene.worldentity)
12142                 RSurf_ActiveWorldEntity();
12143         else
12144                 RSurf_ActiveModelEntity(ent, false, false, false);
12145
12146         decalsystem->lastupdatetime = r_refdef.scene.time;
12147
12148         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
12149
12150         // update vertex positions for animated models
12151         v3f = decalsystem->vertex3f;
12152         c4f = decalsystem->color4f;
12153         t2f = decalsystem->texcoord2f;
12154         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
12155         {
12156                 if (!decal->color4f[0][3])
12157                         continue;
12158
12159                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
12160                         continue;
12161
12162                 // skip backfaces
12163                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
12164                         continue;
12165
12166                 // update color values for fading decals
12167                 if (decal->lived >= cl_decals_time.value)
12168                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
12169                 else
12170                         alpha = 1.0f;
12171
12172                 c4f[ 0] = decal->color4f[0][0] * alpha;
12173                 c4f[ 1] = decal->color4f[0][1] * alpha;
12174                 c4f[ 2] = decal->color4f[0][2] * alpha;
12175                 c4f[ 3] = 1;
12176                 c4f[ 4] = decal->color4f[1][0] * alpha;
12177                 c4f[ 5] = decal->color4f[1][1] * alpha;
12178                 c4f[ 6] = decal->color4f[1][2] * alpha;
12179                 c4f[ 7] = 1;
12180                 c4f[ 8] = decal->color4f[2][0] * alpha;
12181                 c4f[ 9] = decal->color4f[2][1] * alpha;
12182                 c4f[10] = decal->color4f[2][2] * alpha;
12183                 c4f[11] = 1;
12184
12185                 t2f[0] = decal->texcoord2f[0][0];
12186                 t2f[1] = decal->texcoord2f[0][1];
12187                 t2f[2] = decal->texcoord2f[1][0];
12188                 t2f[3] = decal->texcoord2f[1][1];
12189                 t2f[4] = decal->texcoord2f[2][0];
12190                 t2f[5] = decal->texcoord2f[2][1];
12191
12192                 // update vertex positions for animated models
12193                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
12194                 {
12195                         e = rsurface.modelelement3i + 3*decal->triangleindex;
12196                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
12197                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
12198                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
12199                 }
12200                 else
12201                 {
12202                         VectorCopy(decal->vertex3f[0], v3f);
12203                         VectorCopy(decal->vertex3f[1], v3f + 3);
12204                         VectorCopy(decal->vertex3f[2], v3f + 6);
12205                 }
12206
12207                 if (r_refdef.fogenabled)
12208                 {
12209                         alpha = RSurf_FogVertex(v3f);
12210                         VectorScale(c4f, alpha, c4f);
12211                         alpha = RSurf_FogVertex(v3f + 3);
12212                         VectorScale(c4f + 4, alpha, c4f + 4);
12213                         alpha = RSurf_FogVertex(v3f + 6);
12214                         VectorScale(c4f + 8, alpha, c4f + 8);
12215                 }
12216
12217                 v3f += 9;
12218                 c4f += 12;
12219                 t2f += 6;
12220                 numtris++;
12221         }
12222
12223         if (numtris > 0)
12224         {
12225                 r_refdef.stats[r_stat_drawndecals] += numtris;
12226
12227                 // now render the decals all at once
12228                 // (this assumes they all use one particle font texture!)
12229                 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);
12230 //              R_Mesh_ResetTextureState();
12231                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
12232                 GL_DepthMask(false);
12233                 GL_DepthRange(0, 1);
12234                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
12235                 GL_DepthTest(true);
12236                 GL_CullFace(GL_NONE);
12237                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
12238                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
12239                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
12240         }
12241 }
12242
12243 static void R_DrawModelDecals(void)
12244 {
12245         int i, numdecals;
12246
12247         // fade faster when there are too many decals
12248         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12249         for (i = 0;i < r_refdef.scene.numentities;i++)
12250                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12251
12252         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
12253         for (i = 0;i < r_refdef.scene.numentities;i++)
12254                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12255                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
12256
12257         R_DecalSystem_ApplySplatEntitiesQueue();
12258
12259         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
12260         for (i = 0;i < r_refdef.scene.numentities;i++)
12261                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
12262
12263         r_refdef.stats[r_stat_totaldecals] += numdecals;
12264
12265         if (r_showsurfaces.integer)
12266                 return;
12267
12268         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
12269
12270         for (i = 0;i < r_refdef.scene.numentities;i++)
12271         {
12272                 if (!r_refdef.viewcache.entityvisible[i])
12273                         continue;
12274                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
12275                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
12276         }
12277 }
12278
12279 extern cvar_t mod_collision_bih;
12280 static void R_DrawDebugModel(void)
12281 {
12282         entity_render_t *ent = rsurface.entity;
12283         int i, j, flagsmask;
12284         const msurface_t *surface;
12285         dp_model_t *model = ent->model;
12286
12287         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
12288                 return;
12289
12290         if (r_showoverdraw.value > 0)
12291         {
12292                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
12293                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12294                 R_SetupShader_Generic_NoTexture(false, false);
12295                 GL_DepthTest(false);
12296                 GL_DepthMask(false);
12297                 GL_DepthRange(0, 1);
12298                 GL_BlendFunc(GL_ONE, GL_ONE);
12299                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12300                 {
12301                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12302                                 continue;
12303                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12304                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12305                         {
12306                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
12307                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
12308                                 if (!rsurface.texture->currentlayers->depthmask)
12309                                         GL_Color(c, 0, 0, 1.0f);
12310                                 else if (ent == r_refdef.scene.worldentity)
12311                                         GL_Color(c, c, c, 1.0f);
12312                                 else
12313                                         GL_Color(0, c, 0, 1.0f);
12314                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12315                                 RSurf_DrawBatch();
12316                         }
12317                 }
12318                 rsurface.texture = NULL;
12319         }
12320
12321         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
12322
12323 //      R_Mesh_ResetTextureState();
12324         R_SetupShader_Generic_NoTexture(false, false);
12325         GL_DepthRange(0, 1);
12326         GL_DepthTest(!r_showdisabledepthtest.integer);
12327         GL_DepthMask(false);
12328         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12329
12330         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
12331         {
12332                 int triangleindex;
12333                 int bihleafindex;
12334                 qboolean cullbox = false;
12335                 const q3mbrush_t *brush;
12336                 const bih_t *bih = &model->collision_bih;
12337                 const bih_leaf_t *bihleaf;
12338                 float vertex3f[3][3];
12339                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
12340                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
12341                 {
12342                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
12343                                 continue;
12344                         switch (bihleaf->type)
12345                         {
12346                         case BIH_BRUSH:
12347                                 brush = model->brush.data_brushes + bihleaf->itemindex;
12348                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
12349                                 {
12350                                         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);
12351                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
12352                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
12353                                 }
12354                                 break;
12355                         case BIH_COLLISIONTRIANGLE:
12356                                 triangleindex = bihleaf->itemindex;
12357                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
12358                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
12359                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
12360                                 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);
12361                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12362                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12363                                 break;
12364                         case BIH_RENDERTRIANGLE:
12365                                 triangleindex = bihleaf->itemindex;
12366                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
12367                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
12368                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
12369                                 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);
12370                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
12371                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
12372                                 break;
12373                         }
12374                 }
12375         }
12376
12377         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
12378
12379 #ifndef USE_GLES2
12380         if (r_showtris.integer && qglPolygonMode)
12381         {
12382                 if (r_showdisabledepthtest.integer)
12383                 {
12384                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12385                         GL_DepthMask(false);
12386                 }
12387                 else
12388                 {
12389                         GL_BlendFunc(GL_ONE, GL_ZERO);
12390                         GL_DepthMask(true);
12391                 }
12392                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
12393                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12394                 {
12395                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12396                                 continue;
12397                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12398                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12399                         {
12400                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12401                                 if (!rsurface.texture->currentlayers->depthmask)
12402                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
12403                                 else if (ent == r_refdef.scene.worldentity)
12404                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
12405                                 else
12406                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
12407                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
12408                                 RSurf_DrawBatch();
12409                         }
12410                 }
12411                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
12412                 rsurface.texture = NULL;
12413         }
12414
12415         if (r_shownormals.value != 0 && qglBegin)
12416         {
12417                 int l, k;
12418                 vec3_t v;
12419                 if (r_showdisabledepthtest.integer)
12420                 {
12421                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
12422                         GL_DepthMask(false);
12423                 }
12424                 else
12425                 {
12426                         GL_BlendFunc(GL_ONE, GL_ZERO);
12427                         GL_DepthMask(true);
12428                 }
12429                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
12430                 {
12431                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
12432                                 continue;
12433                         rsurface.texture = R_GetCurrentTexture(surface->texture);
12434                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
12435                         {
12436                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
12437                                 qglBegin(GL_LINES);
12438                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
12439                                 {
12440                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12441                                         {
12442                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12443                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12444                                                 qglVertex3f(v[0], v[1], v[2]);
12445                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12446                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12447                                                 qglVertex3f(v[0], v[1], v[2]);
12448                                         }
12449                                 }
12450                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
12451                                 {
12452                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12453                                         {
12454                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12455                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
12456                                                 qglVertex3f(v[0], v[1], v[2]);
12457                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
12458                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12459                                                 qglVertex3f(v[0], v[1], v[2]);
12460                                         }
12461                                 }
12462                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
12463                                 {
12464                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12465                                         {
12466                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12467                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
12468                                                 qglVertex3f(v[0], v[1], v[2]);
12469                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
12470                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12471                                                 qglVertex3f(v[0], v[1], v[2]);
12472                                         }
12473                                 }
12474                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
12475                                 {
12476                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
12477                                         {
12478                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
12479                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
12480                                                 qglVertex3f(v[0], v[1], v[2]);
12481                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
12482                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
12483                                                 qglVertex3f(v[0], v[1], v[2]);
12484                                         }
12485                                 }
12486                                 qglEnd();
12487                                 CHECKGLERROR
12488                         }
12489                 }
12490                 rsurface.texture = NULL;
12491         }
12492 #endif
12493 }
12494
12495 int r_maxsurfacelist = 0;
12496 const msurface_t **r_surfacelist = NULL;
12497 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12498 {
12499         int i, j, endj, flagsmask;
12500         dp_model_t *model = r_refdef.scene.worldmodel;
12501         msurface_t *surfaces;
12502         unsigned char *update;
12503         int numsurfacelist = 0;
12504         if (model == NULL)
12505                 return;
12506
12507         if (r_maxsurfacelist < model->num_surfaces)
12508         {
12509                 r_maxsurfacelist = model->num_surfaces;
12510                 if (r_surfacelist)
12511                         Mem_Free((msurface_t**)r_surfacelist);
12512                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12513         }
12514
12515         RSurf_ActiveWorldEntity();
12516
12517         surfaces = model->data_surfaces;
12518         update = model->brushq1.lightmapupdateflags;
12519
12520         // update light styles on this submodel
12521         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12522         {
12523                 model_brush_lightstyleinfo_t *style;
12524                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12525                 {
12526                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12527                         {
12528                                 int *list = style->surfacelist;
12529                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12530                                 for (j = 0;j < style->numsurfaces;j++)
12531                                         update[list[j]] = true;
12532                         }
12533                 }
12534         }
12535
12536         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12537
12538         if (debug)
12539         {
12540                 R_DrawDebugModel();
12541                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12542                 return;
12543         }
12544
12545         rsurface.lightmaptexture = NULL;
12546         rsurface.deluxemaptexture = NULL;
12547         rsurface.uselightmaptexture = false;
12548         rsurface.texture = NULL;
12549         rsurface.rtlight = NULL;
12550         numsurfacelist = 0;
12551         // add visible surfaces to draw list
12552         for (i = 0;i < model->nummodelsurfaces;i++)
12553         {
12554                 j = model->sortedmodelsurfaces[i];
12555                 if (r_refdef.viewcache.world_surfacevisible[j])
12556                         r_surfacelist[numsurfacelist++] = surfaces + j;
12557         }
12558         // update lightmaps if needed
12559         if (model->brushq1.firstrender)
12560         {
12561                 model->brushq1.firstrender = false;
12562                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12563                         if (update[j])
12564                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12565         }
12566         else if (update)
12567         {
12568                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12569                         if (r_refdef.viewcache.world_surfacevisible[j])
12570                                 if (update[j])
12571                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
12572         }
12573         // don't do anything if there were no surfaces
12574         if (!numsurfacelist)
12575         {
12576                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12577                 return;
12578         }
12579         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12580
12581         // add to stats if desired
12582         if (r_speeds.integer && !skysurfaces && !depthonly)
12583         {
12584                 r_refdef.stats[r_stat_world_surfaces] += numsurfacelist;
12585                 for (j = 0;j < numsurfacelist;j++)
12586                         r_refdef.stats[r_stat_world_triangles] += r_surfacelist[j]->num_triangles;
12587         }
12588
12589         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12590 }
12591
12592 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
12593 {
12594         int i, j, endj, flagsmask;
12595         dp_model_t *model = ent->model;
12596         msurface_t *surfaces;
12597         unsigned char *update;
12598         int numsurfacelist = 0;
12599         if (model == NULL)
12600                 return;
12601
12602         if (r_maxsurfacelist < model->num_surfaces)
12603         {
12604                 r_maxsurfacelist = model->num_surfaces;
12605                 if (r_surfacelist)
12606                         Mem_Free((msurface_t **)r_surfacelist);
12607                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
12608         }
12609
12610         // if the model is static it doesn't matter what value we give for
12611         // wantnormals and wanttangents, so this logic uses only rules applicable
12612         // to a model, knowing that they are meaningless otherwise
12613         if (ent == r_refdef.scene.worldentity)
12614                 RSurf_ActiveWorldEntity();
12615         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
12616                 RSurf_ActiveModelEntity(ent, false, false, false);
12617         else if (prepass)
12618                 RSurf_ActiveModelEntity(ent, true, true, true);
12619         else if (depthonly)
12620         {
12621                 switch (vid.renderpath)
12622                 {
12623                 case RENDERPATH_GL20:
12624                 case RENDERPATH_D3D9:
12625                 case RENDERPATH_D3D10:
12626                 case RENDERPATH_D3D11:
12627                 case RENDERPATH_SOFT:
12628                 case RENDERPATH_GLES2:
12629                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12630                         break;
12631                 case RENDERPATH_GL11:
12632                 case RENDERPATH_GL13:
12633                 case RENDERPATH_GLES1:
12634                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12635                         break;
12636                 }
12637         }
12638         else
12639         {
12640                 switch (vid.renderpath)
12641                 {
12642                 case RENDERPATH_GL20:
12643                 case RENDERPATH_D3D9:
12644                 case RENDERPATH_D3D10:
12645                 case RENDERPATH_D3D11:
12646                 case RENDERPATH_SOFT:
12647                 case RENDERPATH_GLES2:
12648                         RSurf_ActiveModelEntity(ent, true, true, false);
12649                         break;
12650                 case RENDERPATH_GL11:
12651                 case RENDERPATH_GL13:
12652                 case RENDERPATH_GLES1:
12653                         RSurf_ActiveModelEntity(ent, true, false, false);
12654                         break;
12655                 }
12656         }
12657
12658         surfaces = model->data_surfaces;
12659         update = model->brushq1.lightmapupdateflags;
12660
12661         // update light styles
12662         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12663         {
12664                 model_brush_lightstyleinfo_t *style;
12665                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12666                 {
12667                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12668                         {
12669                                 int *list = style->surfacelist;
12670                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12671                                 for (j = 0;j < style->numsurfaces;j++)
12672                                         update[list[j]] = true;
12673                         }
12674                 }
12675         }
12676
12677         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12678
12679         if (debug)
12680         {
12681                 R_DrawDebugModel();
12682                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12683                 return;
12684         }
12685
12686         rsurface.lightmaptexture = NULL;
12687         rsurface.deluxemaptexture = NULL;
12688         rsurface.uselightmaptexture = false;
12689         rsurface.texture = NULL;
12690         rsurface.rtlight = NULL;
12691         numsurfacelist = 0;
12692         // add visible surfaces to draw list
12693         for (i = 0;i < model->nummodelsurfaces;i++)
12694                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12695         // don't do anything if there were no surfaces
12696         if (!numsurfacelist)
12697         {
12698                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12699                 return;
12700         }
12701         // update lightmaps if needed
12702         if (update)
12703         {
12704                 int updated = 0;
12705                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12706                 {
12707                         if (update[j])
12708                         {
12709                                 updated++;
12710                                 R_BuildLightMap(ent, surfaces + j);
12711                         }
12712                 }
12713         }
12714
12715         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12716
12717         // add to stats if desired
12718         if (r_speeds.integer && !skysurfaces && !depthonly)
12719         {
12720                 r_refdef.stats[r_stat_entities_surfaces] += numsurfacelist;
12721                 for (j = 0;j < numsurfacelist;j++)
12722                         r_refdef.stats[r_stat_entities_triangles] += r_surfacelist[j]->num_triangles;
12723         }
12724
12725         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12726 }
12727
12728 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12729 {
12730         static texture_t texture;
12731         static msurface_t surface;
12732         const msurface_t *surfacelist = &surface;
12733
12734         // fake enough texture and surface state to render this geometry
12735
12736         texture.update_lastrenderframe = -1; // regenerate this texture
12737         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12738         texture.basealpha = 1.0f;
12739         texture.currentskinframe = skinframe;
12740         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12741         texture.offsetmapping = OFFSETMAPPING_OFF;
12742         texture.offsetscale = 1;
12743         texture.specularscalemod = 1;
12744         texture.specularpowermod = 1;
12745         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12746         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12747         // JUST GREP FOR "specularscalemod = 1".
12748
12749         surface.texture = &texture;
12750         surface.num_triangles = numtriangles;
12751         surface.num_firsttriangle = firsttriangle;
12752         surface.num_vertices = numvertices;
12753         surface.num_firstvertex = firstvertex;
12754
12755         // now render it
12756         rsurface.texture = R_GetCurrentTexture(surface.texture);
12757         rsurface.lightmaptexture = NULL;
12758         rsurface.deluxemaptexture = NULL;
12759         rsurface.uselightmaptexture = false;
12760         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12761 }
12762
12763 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)
12764 {
12765         static msurface_t surface;
12766         const msurface_t *surfacelist = &surface;
12767
12768         // fake enough texture and surface state to render this geometry
12769         surface.texture = texture;
12770         surface.num_triangles = numtriangles;
12771         surface.num_firsttriangle = firsttriangle;
12772         surface.num_vertices = numvertices;
12773         surface.num_firstvertex = firstvertex;
12774
12775         // now render it
12776         rsurface.texture = R_GetCurrentTexture(surface.texture);
12777         rsurface.lightmaptexture = NULL;
12778         rsurface.deluxemaptexture = NULL;
12779         rsurface.uselightmaptexture = false;
12780         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12781 }