]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
958a341b5a201b60dad5451dc53a2b619301f33d
[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
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 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!"};
54 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!"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 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)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 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"};
60 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"};
61 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"};
62 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"};
63 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"};
64 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"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 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"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 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)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 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"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 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"};
80 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"};
81 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"};
82 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
83 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
84 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)"};
85 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
86 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
87 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"};
88 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"};
89 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
90 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"};
91 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"};
92 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"};
93 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
94 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
95 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
96 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
97 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
98 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
99 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
100 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)"};
101 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)"};
102 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
103 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
104 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
105 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
106 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
107
108 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
109 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
110 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
111
112 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
113 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
114 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
115 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."};
116 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
117 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
118 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
119 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."};
120 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
121 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
122 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
123 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."};
124 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
125 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"};
126 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"};
127 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
128 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
129 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
130 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
131 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
132 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"};
133 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
134 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
135 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
136 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
137 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
138
139 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
140 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
141 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
142 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
143 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
144 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
145 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
146 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
147
148 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)"};
149 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"};
150
151 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
152 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
153 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
154
155 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"};
156 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"};
157 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"};
158 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
159 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
160 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"};
161 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)"};
162 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)"};
163 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
164
165 cvar_t r_glsl_skeletal = {CVAR_SAVE, "r_glsl_skeletal", "1", "render skeletal models faster using a gpu-skinning technique"};
166 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)"};
167 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
168 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)"};
169 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
170 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)"};
171 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)"};
172 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
173 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"};
174 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."};
175 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
176 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)"};
177 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)"};
178 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)"};
179 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)"};
180 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)"};
181 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)"};
182 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)"};
183 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)"};
184
185 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)"};
186 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
187 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"};
188 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
189 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
190 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
191 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"};
192 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"};
193 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)"};
194
195 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
196 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
197 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
198 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
199
200 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
201 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
202
203 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
204 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
205 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
206 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
207 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
208 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
209
210 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
211 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
212 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
213 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
214 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
215 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
216 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
217 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
218 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
219 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
220
221 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"};
222
223 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"};
224
225 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers), a value of 2 keeps normalmap shading"};
226
227 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
228
229 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)"};
230 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)"};
231
232 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
233 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"};
234
235 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."};
236
237 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)"};
238
239 extern cvar_t v_glslgamma;
240 extern cvar_t v_glslgamma_2d;
241
242 extern qboolean v_flipped_state;
243
244 r_framebufferstate_t r_fb;
245
246 /// shadow volume bsp struct with automatically growing nodes buffer
247 svbsp_t r_svbsp;
248
249 rtexture_t *r_texture_blanknormalmap;
250 rtexture_t *r_texture_white;
251 rtexture_t *r_texture_grey128;
252 rtexture_t *r_texture_black;
253 rtexture_t *r_texture_notexture;
254 rtexture_t *r_texture_whitecube;
255 rtexture_t *r_texture_normalizationcube;
256 rtexture_t *r_texture_fogattenuation;
257 rtexture_t *r_texture_fogheighttexture;
258 rtexture_t *r_texture_gammaramps;
259 unsigned int r_texture_gammaramps_serial;
260 //rtexture_t *r_texture_fogintensity;
261 rtexture_t *r_texture_reflectcube;
262
263 // TODO: hash lookups?
264 typedef struct cubemapinfo_s
265 {
266         char basename[64];
267         rtexture_t *texture;
268 }
269 cubemapinfo_t;
270
271 int r_texture_numcubemaps;
272 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
273
274 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
275 unsigned int r_numqueries;
276 unsigned int r_maxqueries;
277
278 typedef struct r_qwskincache_s
279 {
280         char name[MAX_QPATH];
281         skinframe_t *skinframe;
282 }
283 r_qwskincache_t;
284
285 static r_qwskincache_t *r_qwskincache;
286 static int r_qwskincache_size;
287
288 /// vertex coordinates for a quad that covers the screen exactly
289 extern const float r_screenvertex3f[12];
290 extern const float r_d3dscreenvertex3f[12];
291 const float r_screenvertex3f[12] =
292 {
293         0, 0, 0,
294         1, 0, 0,
295         1, 1, 0,
296         0, 1, 0
297 };
298 const float r_d3dscreenvertex3f[12] =
299 {
300         0, 1, 0,
301         1, 1, 0,
302         1, 0, 0,
303         0, 0, 0
304 };
305
306 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
307 {
308         int i;
309         for (i = 0;i < verts;i++)
310         {
311                 out[0] = in[0] * r;
312                 out[1] = in[1] * g;
313                 out[2] = in[2] * b;
314                 out[3] = in[3];
315                 in += 4;
316                 out += 4;
317         }
318 }
319
320 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
321 {
322         int i;
323         for (i = 0;i < verts;i++)
324         {
325                 out[0] = r;
326                 out[1] = g;
327                 out[2] = b;
328                 out[3] = a;
329                 out += 4;
330         }
331 }
332
333 // FIXME: move this to client?
334 void FOG_clear(void)
335 {
336         if (gamemode == GAME_NEHAHRA)
337         {
338                 Cvar_Set("gl_fogenable", "0");
339                 Cvar_Set("gl_fogdensity", "0.2");
340                 Cvar_Set("gl_fogred", "0.3");
341                 Cvar_Set("gl_foggreen", "0.3");
342                 Cvar_Set("gl_fogblue", "0.3");
343         }
344         r_refdef.fog_density = 0;
345         r_refdef.fog_red = 0;
346         r_refdef.fog_green = 0;
347         r_refdef.fog_blue = 0;
348         r_refdef.fog_alpha = 1;
349         r_refdef.fog_start = 0;
350         r_refdef.fog_end = 16384;
351         r_refdef.fog_height = 1<<30;
352         r_refdef.fog_fadedepth = 128;
353         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
354 }
355
356 static void R_BuildBlankTextures(void)
357 {
358         unsigned char data[4];
359         data[2] = 128; // normal X
360         data[1] = 128; // normal Y
361         data[0] = 255; // normal Z
362         data[3] = 255; // height
363         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
364         data[0] = 255;
365         data[1] = 255;
366         data[2] = 255;
367         data[3] = 255;
368         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
369         data[0] = 128;
370         data[1] = 128;
371         data[2] = 128;
372         data[3] = 255;
373         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
374         data[0] = 0;
375         data[1] = 0;
376         data[2] = 0;
377         data[3] = 255;
378         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
379 }
380
381 static void R_BuildNoTexture(void)
382 {
383         int x, y;
384         unsigned char pix[16][16][4];
385         // this makes a light grey/dark grey checkerboard texture
386         for (y = 0;y < 16;y++)
387         {
388                 for (x = 0;x < 16;x++)
389                 {
390                         if ((y < 8) ^ (x < 8))
391                         {
392                                 pix[y][x][0] = 128;
393                                 pix[y][x][1] = 128;
394                                 pix[y][x][2] = 128;
395                                 pix[y][x][3] = 255;
396                         }
397                         else
398                         {
399                                 pix[y][x][0] = 64;
400                                 pix[y][x][1] = 64;
401                                 pix[y][x][2] = 64;
402                                 pix[y][x][3] = 255;
403                         }
404                 }
405         }
406         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
407 }
408
409 static void R_BuildWhiteCube(void)
410 {
411         unsigned char data[6*1*1*4];
412         memset(data, 255, sizeof(data));
413         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
414 }
415
416 static void R_BuildNormalizationCube(void)
417 {
418         int x, y, side;
419         vec3_t v;
420         vec_t s, t, intensity;
421 #define NORMSIZE 64
422         unsigned char *data;
423         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
424         for (side = 0;side < 6;side++)
425         {
426                 for (y = 0;y < NORMSIZE;y++)
427                 {
428                         for (x = 0;x < NORMSIZE;x++)
429                         {
430                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
431                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
432                                 switch(side)
433                                 {
434                                 default:
435                                 case 0:
436                                         v[0] = 1;
437                                         v[1] = -t;
438                                         v[2] = -s;
439                                         break;
440                                 case 1:
441                                         v[0] = -1;
442                                         v[1] = -t;
443                                         v[2] = s;
444                                         break;
445                                 case 2:
446                                         v[0] = s;
447                                         v[1] = 1;
448                                         v[2] = t;
449                                         break;
450                                 case 3:
451                                         v[0] = s;
452                                         v[1] = -1;
453                                         v[2] = -t;
454                                         break;
455                                 case 4:
456                                         v[0] = s;
457                                         v[1] = -t;
458                                         v[2] = 1;
459                                         break;
460                                 case 5:
461                                         v[0] = -s;
462                                         v[1] = -t;
463                                         v[2] = -1;
464                                         break;
465                                 }
466                                 intensity = 127.0f / sqrt(DotProduct(v, v));
467                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
468                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
469                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
470                                 data[((side*64+y)*64+x)*4+3] = 255;
471                         }
472                 }
473         }
474         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
475         Mem_Free(data);
476 }
477
478 static void R_BuildFogTexture(void)
479 {
480         int x, b;
481 #define FOGWIDTH 256
482         unsigned char data1[FOGWIDTH][4];
483         //unsigned char data2[FOGWIDTH][4];
484         double d, r, alpha;
485
486         r_refdef.fogmasktable_start = r_refdef.fog_start;
487         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
488         r_refdef.fogmasktable_range = r_refdef.fogrange;
489         r_refdef.fogmasktable_density = r_refdef.fog_density;
490
491         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
492         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
493         {
494                 d = (x * r - r_refdef.fogmasktable_start);
495                 if(developer_extra.integer)
496                         Con_DPrintf("%f ", d);
497                 d = max(0, d);
498                 if (r_fog_exp2.integer)
499                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
500                 else
501                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
502                 if(developer_extra.integer)
503                         Con_DPrintf(" : %f ", alpha);
504                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
505                 if(developer_extra.integer)
506                         Con_DPrintf(" = %f\n", alpha);
507                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
508         }
509
510         for (x = 0;x < FOGWIDTH;x++)
511         {
512                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
513                 data1[x][0] = b;
514                 data1[x][1] = b;
515                 data1[x][2] = b;
516                 data1[x][3] = 255;
517                 //data2[x][0] = 255 - b;
518                 //data2[x][1] = 255 - b;
519                 //data2[x][2] = 255 - b;
520                 //data2[x][3] = 255;
521         }
522         if (r_texture_fogattenuation)
523         {
524                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
525                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
526         }
527         else
528         {
529                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
530                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
531         }
532 }
533
534 static void R_BuildFogHeightTexture(void)
535 {
536         unsigned char *inpixels;
537         int size;
538         int x;
539         int y;
540         int j;
541         float c[4];
542         float f;
543         inpixels = NULL;
544         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
545         if (r_refdef.fogheighttexturename[0])
546                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
547         if (!inpixels)
548         {
549                 r_refdef.fog_height_tablesize = 0;
550                 if (r_texture_fogheighttexture)
551                         R_FreeTexture(r_texture_fogheighttexture);
552                 r_texture_fogheighttexture = NULL;
553                 if (r_refdef.fog_height_table2d)
554                         Mem_Free(r_refdef.fog_height_table2d);
555                 r_refdef.fog_height_table2d = NULL;
556                 if (r_refdef.fog_height_table1d)
557                         Mem_Free(r_refdef.fog_height_table1d);
558                 r_refdef.fog_height_table1d = NULL;
559                 return;
560         }
561         size = image_width;
562         r_refdef.fog_height_tablesize = size;
563         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
564         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
565         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
566         Mem_Free(inpixels);
567         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
568         // average fog color table accounting for every fog layer between a point
569         // and the camera.  (Note: attenuation is handled separately!)
570         for (y = 0;y < size;y++)
571         {
572                 for (x = 0;x < size;x++)
573                 {
574                         Vector4Clear(c);
575                         f = 0;
576                         if (x < y)
577                         {
578                                 for (j = x;j <= y;j++)
579                                 {
580                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
581                                         f++;
582                                 }
583                         }
584                         else
585                         {
586                                 for (j = x;j >= y;j--)
587                                 {
588                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
589                                         f++;
590                                 }
591                         }
592                         f = 1.0f / f;
593                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
594                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
595                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
596                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
597                 }
598         }
599         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
600 }
601
602 //=======================================================================================================================================================
603
604 static const char *builtinshaderstring =
605 #include "shader_glsl.h"
606 ;
607
608 const char *builtinhlslshaderstring =
609 #include "shader_hlsl.h"
610 ;
611
612 char *glslshaderstring = NULL;
613 char *hlslshaderstring = NULL;
614
615 //=======================================================================================================================================================
616
617 typedef struct shaderpermutationinfo_s
618 {
619         const char *pretext;
620         const char *name;
621 }
622 shaderpermutationinfo_t;
623
624 typedef struct shadermodeinfo_s
625 {
626         const char *vertexfilename;
627         const char *geometryfilename;
628         const char *fragmentfilename;
629         const char *pretext;
630         const char *name;
631 }
632 shadermodeinfo_t;
633
634 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
635 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
636 {
637         {"#define USEDIFFUSE\n", " diffuse"},
638         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
639         {"#define USEVIEWTINT\n", " viewtint"},
640         {"#define USECOLORMAPPING\n", " colormapping"},
641         {"#define USESATURATION\n", " saturation"},
642         {"#define USEFOGINSIDE\n", " foginside"},
643         {"#define USEFOGOUTSIDE\n", " fogoutside"},
644         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
645         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
646         {"#define USEGAMMARAMPS\n", " gammaramps"},
647         {"#define USECUBEFILTER\n", " cubefilter"},
648         {"#define USEGLOW\n", " glow"},
649         {"#define USEBLOOM\n", " bloom"},
650         {"#define USESPECULAR\n", " specular"},
651         {"#define USEPOSTPROCESSING\n", " postprocessing"},
652         {"#define USEREFLECTION\n", " reflection"},
653         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
654         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
655         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
656         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
657         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
658         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
659         {"#define USEALPHAKILL\n", " alphakill"},
660         {"#define USEREFLECTCUBE\n", " reflectcube"},
661         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
662         {"#define USEBOUNCEGRID\n", " bouncegrid"},
663         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
664         {"#define USETRIPPY\n", " trippy"},
665         {"#define USEDEPTHRGB\n", " depthrgb"},
666         {"#define USEALPHAGENVERTEX\n", " alphagenvertex"},
667         {"#define USESKELETAL\n", " skeletal"}
668 };
669
670 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
671 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
672 {
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
685         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
686         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
687         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
688         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
689         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
690         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
691 };
692
693 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
694 {
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
707         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
708         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
709         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
710         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
711         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
712         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
713 };
714
715 struct r_glsl_permutation_s;
716 typedef struct r_glsl_permutation_s
717 {
718         /// hash lookup data
719         struct r_glsl_permutation_s *hashnext;
720         unsigned int mode;
721         unsigned int permutation;
722
723         /// indicates if we have tried compiling this permutation already
724         qboolean compiled;
725         /// 0 if compilation failed
726         int program;
727         // texture units assigned to each detected uniform
728         int tex_Texture_First;
729         int tex_Texture_Second;
730         int tex_Texture_GammaRamps;
731         int tex_Texture_Normal;
732         int tex_Texture_Color;
733         int tex_Texture_Gloss;
734         int tex_Texture_Glow;
735         int tex_Texture_SecondaryNormal;
736         int tex_Texture_SecondaryColor;
737         int tex_Texture_SecondaryGloss;
738         int tex_Texture_SecondaryGlow;
739         int tex_Texture_Pants;
740         int tex_Texture_Shirt;
741         int tex_Texture_FogHeightTexture;
742         int tex_Texture_FogMask;
743         int tex_Texture_Lightmap;
744         int tex_Texture_Deluxemap;
745         int tex_Texture_Attenuation;
746         int tex_Texture_Cube;
747         int tex_Texture_Refraction;
748         int tex_Texture_Reflection;
749         int tex_Texture_ShadowMap2D;
750         int tex_Texture_CubeProjection;
751         int tex_Texture_ScreenNormalMap;
752         int tex_Texture_ScreenDiffuse;
753         int tex_Texture_ScreenSpecular;
754         int tex_Texture_ReflectMask;
755         int tex_Texture_ReflectCube;
756         int tex_Texture_BounceGrid;
757         /// locations of detected uniforms in program object, or -1 if not found
758         int loc_Texture_First;
759         int loc_Texture_Second;
760         int loc_Texture_GammaRamps;
761         int loc_Texture_Normal;
762         int loc_Texture_Color;
763         int loc_Texture_Gloss;
764         int loc_Texture_Glow;
765         int loc_Texture_SecondaryNormal;
766         int loc_Texture_SecondaryColor;
767         int loc_Texture_SecondaryGloss;
768         int loc_Texture_SecondaryGlow;
769         int loc_Texture_Pants;
770         int loc_Texture_Shirt;
771         int loc_Texture_FogHeightTexture;
772         int loc_Texture_FogMask;
773         int loc_Texture_Lightmap;
774         int loc_Texture_Deluxemap;
775         int loc_Texture_Attenuation;
776         int loc_Texture_Cube;
777         int loc_Texture_Refraction;
778         int loc_Texture_Reflection;
779         int loc_Texture_ShadowMap2D;
780         int loc_Texture_CubeProjection;
781         int loc_Texture_ScreenNormalMap;
782         int loc_Texture_ScreenDiffuse;
783         int loc_Texture_ScreenSpecular;
784         int loc_Texture_ReflectMask;
785         int loc_Texture_ReflectCube;
786         int loc_Texture_BounceGrid;
787         int loc_Alpha;
788         int loc_BloomBlur_Parameters;
789         int loc_ClientTime;
790         int loc_Color_Ambient;
791         int loc_Color_Diffuse;
792         int loc_Color_Specular;
793         int loc_Color_Glow;
794         int loc_Color_Pants;
795         int loc_Color_Shirt;
796         int loc_DeferredColor_Ambient;
797         int loc_DeferredColor_Diffuse;
798         int loc_DeferredColor_Specular;
799         int loc_DeferredMod_Diffuse;
800         int loc_DeferredMod_Specular;
801         int loc_DistortScaleRefractReflect;
802         int loc_EyePosition;
803         int loc_FogColor;
804         int loc_FogHeightFade;
805         int loc_FogPlane;
806         int loc_FogPlaneViewDist;
807         int loc_FogRangeRecip;
808         int loc_LightColor;
809         int loc_LightDir;
810         int loc_LightPosition;
811         int loc_OffsetMapping_ScaleSteps;
812         int loc_OffsetMapping_LodDistance;
813         int loc_OffsetMapping_Bias;
814         int loc_PixelSize;
815         int loc_ReflectColor;
816         int loc_ReflectFactor;
817         int loc_ReflectOffset;
818         int loc_RefractColor;
819         int loc_Saturation;
820         int loc_ScreenCenterRefractReflect;
821         int loc_ScreenScaleRefractReflect;
822         int loc_ScreenToDepth;
823         int loc_ShadowMap_Parameters;
824         int loc_ShadowMap_TextureScale;
825         int loc_SpecularPower;
826         int loc_Skeletal_Transform12;
827         int loc_UserVec1;
828         int loc_UserVec2;
829         int loc_UserVec3;
830         int loc_UserVec4;
831         int loc_ViewTintColor;
832         int loc_ViewToLight;
833         int loc_ModelToLight;
834         int loc_TexMatrix;
835         int loc_BackgroundTexMatrix;
836         int loc_ModelViewProjectionMatrix;
837         int loc_ModelViewMatrix;
838         int loc_PixelToScreenTexCoord;
839         int loc_ModelToReflectCube;
840         int loc_ShadowMapMatrix;
841         int loc_BloomColorSubtract;
842         int loc_NormalmapScrollBlend;
843         int loc_BounceGridMatrix;
844         int loc_BounceGridIntensity;
845 }
846 r_glsl_permutation_t;
847
848 #define SHADERPERMUTATION_HASHSIZE 256
849
850
851 // non-degradable "lightweight" shader parameters to keep the permutations simpler
852 // these can NOT degrade! only use for simple stuff
853 enum
854 {
855         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
856         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
857         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
858         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
859         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
860         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
861         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
862         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
863         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
864         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
865         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
866         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
867         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
868 };
869 #define SHADERSTATICPARMS_COUNT 13
870
871 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
872 static int shaderstaticparms_count = 0;
873
874 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
875 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
876
877 extern qboolean r_shadow_shadowmapsampler;
878 extern int r_shadow_shadowmappcf;
879 qboolean R_CompileShader_CheckStaticParms(void)
880 {
881         static int r_compileshader_staticparms_save[1];
882         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
883         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
884
885         // detect all
886         if (r_glsl_saturation_redcompensate.integer)
887                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
888         if (r_glsl_vertextextureblend_usebothalphas.integer)
889                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
890         if (r_shadow_glossexact.integer)
891                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
892         if (r_glsl_postprocess.integer)
893         {
894                 if (r_glsl_postprocess_uservec1_enable.integer)
895                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
896                 if (r_glsl_postprocess_uservec2_enable.integer)
897                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
898                 if (r_glsl_postprocess_uservec3_enable.integer)
899                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
900                 if (r_glsl_postprocess_uservec4_enable.integer)
901                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
902         }
903         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
904                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
905
906         if (r_shadow_shadowmapsampler)
907                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
908         if (r_shadow_shadowmappcf > 1)
909                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
910         else if (r_shadow_shadowmappcf)
911                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
912         if (r_celshading.integer)
913                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
914         if (r_celoutlines.integer)
915                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
916
917         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
918 }
919
920 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
921         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
922                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
923         else \
924                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
925 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
926 {
927         shaderstaticparms_count = 0;
928
929         // emit all
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
935         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
936         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
937         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
938         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
939         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
940         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
941         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
942         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
943 }
944
945 /// information about each possible shader permutation
946 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
947 /// currently selected permutation
948 r_glsl_permutation_t *r_glsl_permutation;
949 /// storage for permutations linked in the hash table
950 memexpandablearray_t r_glsl_permutationarray;
951
952 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
953 {
954         //unsigned int hashdepth = 0;
955         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
956         r_glsl_permutation_t *p;
957         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
958         {
959                 if (p->mode == mode && p->permutation == permutation)
960                 {
961                         //if (hashdepth > 10)
962                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
963                         return p;
964                 }
965                 //hashdepth++;
966         }
967         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
968         p->mode = mode;
969         p->permutation = permutation;
970         p->hashnext = r_glsl_permutationhash[mode][hashindex];
971         r_glsl_permutationhash[mode][hashindex] = p;
972         //if (hashdepth > 10)
973         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
974         return p;
975 }
976
977 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
978 {
979         char *shaderstring;
980         if (!filename || !filename[0])
981                 return NULL;
982         if (!strcmp(filename, "glsl/default.glsl"))
983         {
984                 if (!glslshaderstring)
985                 {
986                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
987                         if (glslshaderstring)
988                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
989                         else
990                                 glslshaderstring = (char *)builtinshaderstring;
991                 }
992                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
993                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
994                 return shaderstring;
995         }
996         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
997         if (shaderstring)
998         {
999                 if (printfromdisknotice)
1000                         Con_DPrintf("from disk %s... ", filename);
1001                 return shaderstring;
1002         }
1003         return shaderstring;
1004 }
1005
1006 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1007 {
1008         int i;
1009         int sampler;
1010         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1011         char *vertexstring, *geometrystring, *fragmentstring;
1012         char permutationname[256];
1013         int vertstrings_count = 0;
1014         int geomstrings_count = 0;
1015         int fragstrings_count = 0;
1016         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1017         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1018         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1019
1020         if (p->compiled)
1021                 return;
1022         p->compiled = true;
1023         p->program = 0;
1024
1025         permutationname[0] = 0;
1026         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1027         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1028         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1029
1030         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1031
1032         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1033         if(vid.support.gl20shaders130)
1034         {
1035                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1036                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1037                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1038                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1039                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1040                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1041         }
1042
1043         // the first pretext is which type of shader to compile as
1044         // (later these will all be bound together as a program object)
1045         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1046         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1047         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1048
1049         // the second pretext is the mode (for example a light source)
1050         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1051         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1052         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1053         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1054
1055         // now add all the permutation pretexts
1056         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1057         {
1058                 if (permutation & (1<<i))
1059                 {
1060                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1061                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1062                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1063                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1064                 }
1065                 else
1066                 {
1067                         // keep line numbers correct
1068                         vertstrings_list[vertstrings_count++] = "\n";
1069                         geomstrings_list[geomstrings_count++] = "\n";
1070                         fragstrings_list[fragstrings_count++] = "\n";
1071                 }
1072         }
1073
1074         // add static parms
1075         R_CompileShader_AddStaticParms(mode, permutation);
1076         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1077         vertstrings_count += shaderstaticparms_count;
1078         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1079         geomstrings_count += shaderstaticparms_count;
1080         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1081         fragstrings_count += shaderstaticparms_count;
1082
1083         // now append the shader text itself
1084         vertstrings_list[vertstrings_count++] = vertexstring;
1085         geomstrings_list[geomstrings_count++] = geometrystring;
1086         fragstrings_list[fragstrings_count++] = fragmentstring;
1087
1088         // if any sources were NULL, clear the respective list
1089         if (!vertexstring)
1090                 vertstrings_count = 0;
1091         if (!geometrystring)
1092                 geomstrings_count = 0;
1093         if (!fragmentstring)
1094                 fragstrings_count = 0;
1095
1096         // compile the shader program
1097         if (vertstrings_count + geomstrings_count + fragstrings_count)
1098                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1099         if (p->program)
1100         {
1101                 CHECKGLERROR
1102                 qglUseProgram(p->program);CHECKGLERROR
1103                 // look up all the uniform variable names we care about, so we don't
1104                 // have to look them up every time we set them
1105
1106                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1107                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1108                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1109                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1110                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1111                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1112                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1113                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1114                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1115                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1116                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1117                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1118                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1119                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1120                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1121                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1122                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1123                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1124                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1125                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1126                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1127                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1128                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1129                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1130                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1131                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1132                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1133                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1134                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1135                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1136                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1137                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1138                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1139                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1140                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1141                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1142                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1143                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1144                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1145                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1146                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1147                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1148                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1149                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1150                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1151                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1152                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1153                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1154                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1155                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1156                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1157                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1158                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1159                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1160                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1161                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1162                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1163                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1164                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1165                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1166                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1167                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1168                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1169                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1170                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1171                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1172                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1173                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1174                 p->loc_Skeletal_Transform12       = qglGetUniformLocation(p->program, "Skeletal_Transform12");
1175                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1176                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1177                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1178                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1179                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1180                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1181                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1182                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1183                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1184                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1185                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1186                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1187                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1188                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1189                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1190                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1191                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1192                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1193                 // initialize the samplers to refer to the texture units we use
1194                 p->tex_Texture_First = -1;
1195                 p->tex_Texture_Second = -1;
1196                 p->tex_Texture_GammaRamps = -1;
1197                 p->tex_Texture_Normal = -1;
1198                 p->tex_Texture_Color = -1;
1199                 p->tex_Texture_Gloss = -1;
1200                 p->tex_Texture_Glow = -1;
1201                 p->tex_Texture_SecondaryNormal = -1;
1202                 p->tex_Texture_SecondaryColor = -1;
1203                 p->tex_Texture_SecondaryGloss = -1;
1204                 p->tex_Texture_SecondaryGlow = -1;
1205                 p->tex_Texture_Pants = -1;
1206                 p->tex_Texture_Shirt = -1;
1207                 p->tex_Texture_FogHeightTexture = -1;
1208                 p->tex_Texture_FogMask = -1;
1209                 p->tex_Texture_Lightmap = -1;
1210                 p->tex_Texture_Deluxemap = -1;
1211                 p->tex_Texture_Attenuation = -1;
1212                 p->tex_Texture_Cube = -1;
1213                 p->tex_Texture_Refraction = -1;
1214                 p->tex_Texture_Reflection = -1;
1215                 p->tex_Texture_ShadowMap2D = -1;
1216                 p->tex_Texture_CubeProjection = -1;
1217                 p->tex_Texture_ScreenNormalMap = -1;
1218                 p->tex_Texture_ScreenDiffuse = -1;
1219                 p->tex_Texture_ScreenSpecular = -1;
1220                 p->tex_Texture_ReflectMask = -1;
1221                 p->tex_Texture_ReflectCube = -1;
1222                 p->tex_Texture_BounceGrid = -1;
1223                 sampler = 0;
1224                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1225                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1226                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1227                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1228                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1229                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1230                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1231                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1232                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1233                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1234                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1235                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1236                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1237                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1238                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1239                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1240                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1241                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1242                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1243                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1244                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1245                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1246                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1247                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1248                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1249                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1250                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1251                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1252                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1253                 CHECKGLERROR
1254                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1255         }
1256         else
1257                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1258
1259         // free the strings
1260         if (vertexstring)
1261                 Mem_Free(vertexstring);
1262         if (geometrystring)
1263                 Mem_Free(geometrystring);
1264         if (fragmentstring)
1265                 Mem_Free(fragmentstring);
1266 }
1267
1268 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1269 {
1270         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1271         if (r_glsl_permutation != perm)
1272         {
1273                 r_glsl_permutation = perm;
1274                 if (!r_glsl_permutation->program)
1275                 {
1276                         if (!r_glsl_permutation->compiled)
1277                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1278                         if (!r_glsl_permutation->program)
1279                         {
1280                                 // remove features until we find a valid permutation
1281                                 int i;
1282                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1283                                 {
1284                                         // reduce i more quickly whenever it would not remove any bits
1285                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1286                                         if (!(permutation & j))
1287                                                 continue;
1288                                         permutation -= j;
1289                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1290                                         if (!r_glsl_permutation->compiled)
1291                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1292                                         if (r_glsl_permutation->program)
1293                                                 break;
1294                                 }
1295                                 if (i >= SHADERPERMUTATION_COUNT)
1296                                 {
1297                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1298                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1299                                         qglUseProgram(0);CHECKGLERROR
1300                                         return; // no bit left to clear, entire mode is broken
1301                                 }
1302                         }
1303                 }
1304                 CHECKGLERROR
1305                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1306         }
1307         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1308         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1309         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1310 }
1311
1312 #ifdef SUPPORTD3D
1313
1314 #ifdef SUPPORTD3D
1315 #include <d3d9.h>
1316 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1317 extern D3DCAPS9 vid_d3d9caps;
1318 #endif
1319
1320 struct r_hlsl_permutation_s;
1321 typedef struct r_hlsl_permutation_s
1322 {
1323         /// hash lookup data
1324         struct r_hlsl_permutation_s *hashnext;
1325         unsigned int mode;
1326         unsigned int permutation;
1327
1328         /// indicates if we have tried compiling this permutation already
1329         qboolean compiled;
1330         /// NULL if compilation failed
1331         IDirect3DVertexShader9 *vertexshader;
1332         IDirect3DPixelShader9 *pixelshader;
1333 }
1334 r_hlsl_permutation_t;
1335
1336 typedef enum D3DVSREGISTER_e
1337 {
1338         D3DVSREGISTER_TexMatrix = 0, // float4x4
1339         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1340         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1341         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1342         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1343         D3DVSREGISTER_ModelToLight = 20, // float4x4
1344         D3DVSREGISTER_EyePosition = 24,
1345         D3DVSREGISTER_FogPlane = 25,
1346         D3DVSREGISTER_LightDir = 26,
1347         D3DVSREGISTER_LightPosition = 27,
1348 }
1349 D3DVSREGISTER_t;
1350
1351 typedef enum D3DPSREGISTER_e
1352 {
1353         D3DPSREGISTER_Alpha = 0,
1354         D3DPSREGISTER_BloomBlur_Parameters = 1,
1355         D3DPSREGISTER_ClientTime = 2,
1356         D3DPSREGISTER_Color_Ambient = 3,
1357         D3DPSREGISTER_Color_Diffuse = 4,
1358         D3DPSREGISTER_Color_Specular = 5,
1359         D3DPSREGISTER_Color_Glow = 6,
1360         D3DPSREGISTER_Color_Pants = 7,
1361         D3DPSREGISTER_Color_Shirt = 8,
1362         D3DPSREGISTER_DeferredColor_Ambient = 9,
1363         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1364         D3DPSREGISTER_DeferredColor_Specular = 11,
1365         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1366         D3DPSREGISTER_DeferredMod_Specular = 13,
1367         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1368         D3DPSREGISTER_EyePosition = 15, // unused
1369         D3DPSREGISTER_FogColor = 16,
1370         D3DPSREGISTER_FogHeightFade = 17,
1371         D3DPSREGISTER_FogPlane = 18,
1372         D3DPSREGISTER_FogPlaneViewDist = 19,
1373         D3DPSREGISTER_FogRangeRecip = 20,
1374         D3DPSREGISTER_LightColor = 21,
1375         D3DPSREGISTER_LightDir = 22, // unused
1376         D3DPSREGISTER_LightPosition = 23,
1377         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1378         D3DPSREGISTER_PixelSize = 25,
1379         D3DPSREGISTER_ReflectColor = 26,
1380         D3DPSREGISTER_ReflectFactor = 27,
1381         D3DPSREGISTER_ReflectOffset = 28,
1382         D3DPSREGISTER_RefractColor = 29,
1383         D3DPSREGISTER_Saturation = 30,
1384         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1385         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1386         D3DPSREGISTER_ScreenToDepth = 33,
1387         D3DPSREGISTER_ShadowMap_Parameters = 34,
1388         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1389         D3DPSREGISTER_SpecularPower = 36,
1390         D3DPSREGISTER_UserVec1 = 37,
1391         D3DPSREGISTER_UserVec2 = 38,
1392         D3DPSREGISTER_UserVec3 = 39,
1393         D3DPSREGISTER_UserVec4 = 40,
1394         D3DPSREGISTER_ViewTintColor = 41,
1395         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1396         D3DPSREGISTER_BloomColorSubtract = 43,
1397         D3DPSREGISTER_ViewToLight = 44, // float4x4
1398         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1399         D3DPSREGISTER_NormalmapScrollBlend = 52,
1400         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1401         D3DPSREGISTER_OffsetMapping_Bias = 54,
1402         // next at 54
1403 }
1404 D3DPSREGISTER_t;
1405
1406 /// information about each possible shader permutation
1407 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1408 /// currently selected permutation
1409 r_hlsl_permutation_t *r_hlsl_permutation;
1410 /// storage for permutations linked in the hash table
1411 memexpandablearray_t r_hlsl_permutationarray;
1412
1413 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1414 {
1415         //unsigned int hashdepth = 0;
1416         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1417         r_hlsl_permutation_t *p;
1418         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1419         {
1420                 if (p->mode == mode && p->permutation == permutation)
1421                 {
1422                         //if (hashdepth > 10)
1423                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1424                         return p;
1425                 }
1426                 //hashdepth++;
1427         }
1428         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1429         p->mode = mode;
1430         p->permutation = permutation;
1431         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1432         r_hlsl_permutationhash[mode][hashindex] = p;
1433         //if (hashdepth > 10)
1434         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1435         return p;
1436 }
1437
1438 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1439 {
1440         char *shaderstring;
1441         if (!filename || !filename[0])
1442                 return NULL;
1443         if (!strcmp(filename, "hlsl/default.hlsl"))
1444         {
1445                 if (!hlslshaderstring)
1446                 {
1447                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1448                         if (hlslshaderstring)
1449                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1450                         else
1451                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1452                 }
1453                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1454                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1455                 return shaderstring;
1456         }
1457         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1458         if (shaderstring)
1459         {
1460                 if (printfromdisknotice)
1461                         Con_DPrintf("from disk %s... ", filename);
1462                 return shaderstring;
1463         }
1464         return shaderstring;
1465 }
1466
1467 #include <d3dx9.h>
1468 //#include <d3dx9shader.h>
1469 //#include <d3dx9mesh.h>
1470
1471 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1472 {
1473         DWORD *vsbin = NULL;
1474         DWORD *psbin = NULL;
1475         fs_offset_t vsbinsize;
1476         fs_offset_t psbinsize;
1477 //      IDirect3DVertexShader9 *vs = NULL;
1478 //      IDirect3DPixelShader9 *ps = NULL;
1479         ID3DXBuffer *vslog = NULL;
1480         ID3DXBuffer *vsbuffer = NULL;
1481         ID3DXConstantTable *vsconstanttable = NULL;
1482         ID3DXBuffer *pslog = NULL;
1483         ID3DXBuffer *psbuffer = NULL;
1484         ID3DXConstantTable *psconstanttable = NULL;
1485         int vsresult = 0;
1486         int psresult = 0;
1487         char temp[MAX_INPUTLINE];
1488         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1489         char vabuf[1024];
1490         qboolean debugshader = gl_paranoid.integer != 0;
1491         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1492         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1493         if (!debugshader)
1494         {
1495                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1496                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1497         }
1498         if ((!vsbin && vertstring) || (!psbin && fragstring))
1499         {
1500                 const char* dllnames_d3dx9 [] =
1501                 {
1502                         "d3dx9_43.dll",
1503                         "d3dx9_42.dll",
1504                         "d3dx9_41.dll",
1505                         "d3dx9_40.dll",
1506                         "d3dx9_39.dll",
1507                         "d3dx9_38.dll",
1508                         "d3dx9_37.dll",
1509                         "d3dx9_36.dll",
1510                         "d3dx9_35.dll",
1511                         "d3dx9_34.dll",
1512                         "d3dx9_33.dll",
1513                         "d3dx9_32.dll",
1514                         "d3dx9_31.dll",
1515                         "d3dx9_30.dll",
1516                         "d3dx9_29.dll",
1517                         "d3dx9_28.dll",
1518                         "d3dx9_27.dll",
1519                         "d3dx9_26.dll",
1520                         "d3dx9_25.dll",
1521                         "d3dx9_24.dll",
1522                         NULL
1523                 };
1524                 dllhandle_t d3dx9_dll = NULL;
1525                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1526                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1527                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1528                 dllfunction_t d3dx9_dllfuncs[] =
1529                 {
1530                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1531                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1532                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1533                         {NULL, NULL}
1534                 };
1535                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1536                 {
1537                         DWORD shaderflags = 0;
1538                         if (debugshader)
1539                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1540                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1541                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1542                         if (vertstring && vertstring[0])
1543                         {
1544                                 if (debugshader)
1545                                 {
1546                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1547                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1548                                 }
1549                                 else
1550                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1551                                 if (vsbuffer)
1552                                 {
1553                                         vsbinsize = ID3DXBuffer_GetBufferSize(vsbuffer);
1554                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1555                                         memcpy(vsbin, ID3DXBuffer_GetBufferPointer(vsbuffer), vsbinsize);
1556                                         ID3DXBuffer_Release(vsbuffer);
1557                                 }
1558                                 if (vslog)
1559                                 {
1560                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(vslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(vslog)));
1561                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1562                                         ID3DXBuffer_Release(vslog);
1563                                 }
1564                         }
1565                         if (fragstring && fragstring[0])
1566                         {
1567                                 if (debugshader)
1568                                 {
1569                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1570                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1571                                 }
1572                                 else
1573                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1574                                 if (psbuffer)
1575                                 {
1576                                         psbinsize = ID3DXBuffer_GetBufferSize(psbuffer);
1577                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1578                                         memcpy(psbin, ID3DXBuffer_GetBufferPointer(psbuffer), psbinsize);
1579                                         ID3DXBuffer_Release(psbuffer);
1580                                 }
1581                                 if (pslog)
1582                                 {
1583                                         strlcpy(temp, (const char *)ID3DXBuffer_GetBufferPointer(pslog), min(sizeof(temp), ID3DXBuffer_GetBufferSize(pslog)));
1584                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1585                                         ID3DXBuffer_Release(pslog);
1586                                 }
1587                         }
1588                         Sys_UnloadLibrary(&d3dx9_dll);
1589                 }
1590                 else
1591                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1592         }
1593         if (vsbin && psbin)
1594         {
1595                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1596                 if (FAILED(vsresult))
1597                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1598                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1599                 if (FAILED(psresult))
1600                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1601         }
1602         // free the shader data
1603         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1604         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1605 }
1606
1607 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1608 {
1609         int i;
1610         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1611         int vertstring_length = 0;
1612         int geomstring_length = 0;
1613         int fragstring_length = 0;
1614         char *t;
1615         char *vertexstring, *geometrystring, *fragmentstring;
1616         char *vertstring, *geomstring, *fragstring;
1617         char permutationname[256];
1618         char cachename[256];
1619         int vertstrings_count = 0;
1620         int geomstrings_count = 0;
1621         int fragstrings_count = 0;
1622         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1623         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1624         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1625
1626         if (p->compiled)
1627                 return;
1628         p->compiled = true;
1629         p->vertexshader = NULL;
1630         p->pixelshader = NULL;
1631
1632         permutationname[0] = 0;
1633         cachename[0] = 0;
1634         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1635         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1636         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1637
1638         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1639         strlcat(cachename, "hlsl/", sizeof(cachename));
1640
1641         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1642         vertstrings_count = 0;
1643         geomstrings_count = 0;
1644         fragstrings_count = 0;
1645         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1646         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1647         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1648
1649         // the first pretext is which type of shader to compile as
1650         // (later these will all be bound together as a program object)
1651         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1652         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1653         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1654
1655         // the second pretext is the mode (for example a light source)
1656         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1657         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1658         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1659         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1660         strlcat(cachename, modeinfo->name, sizeof(cachename));
1661
1662         // now add all the permutation pretexts
1663         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1664         {
1665                 if (permutation & (1<<i))
1666                 {
1667                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1668                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1669                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1670                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1671                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1672                 }
1673                 else
1674                 {
1675                         // keep line numbers correct
1676                         vertstrings_list[vertstrings_count++] = "\n";
1677                         geomstrings_list[geomstrings_count++] = "\n";
1678                         fragstrings_list[fragstrings_count++] = "\n";
1679                 }
1680         }
1681
1682         // add static parms
1683         R_CompileShader_AddStaticParms(mode, permutation);
1684         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1685         vertstrings_count += shaderstaticparms_count;
1686         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1687         geomstrings_count += shaderstaticparms_count;
1688         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1689         fragstrings_count += shaderstaticparms_count;
1690
1691         // replace spaces in the cachename with _ characters
1692         for (i = 0;cachename[i];i++)
1693                 if (cachename[i] == ' ')
1694                         cachename[i] = '_';
1695
1696         // now append the shader text itself
1697         vertstrings_list[vertstrings_count++] = vertexstring;
1698         geomstrings_list[geomstrings_count++] = geometrystring;
1699         fragstrings_list[fragstrings_count++] = fragmentstring;
1700
1701         // if any sources were NULL, clear the respective list
1702         if (!vertexstring)
1703                 vertstrings_count = 0;
1704         if (!geometrystring)
1705                 geomstrings_count = 0;
1706         if (!fragmentstring)
1707                 fragstrings_count = 0;
1708
1709         vertstring_length = 0;
1710         for (i = 0;i < vertstrings_count;i++)
1711                 vertstring_length += strlen(vertstrings_list[i]);
1712         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1713         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1714                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1715
1716         geomstring_length = 0;
1717         for (i = 0;i < geomstrings_count;i++)
1718                 geomstring_length += strlen(geomstrings_list[i]);
1719         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1720         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1721                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1722
1723         fragstring_length = 0;
1724         for (i = 0;i < fragstrings_count;i++)
1725                 fragstring_length += strlen(fragstrings_list[i]);
1726         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1727         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1728                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1729
1730         // try to load the cached shader, or generate one
1731         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1732
1733         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1734                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1735         else
1736                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1737
1738         // free the strings
1739         if (vertstring)
1740                 Mem_Free(vertstring);
1741         if (geomstring)
1742                 Mem_Free(geomstring);
1743         if (fragstring)
1744                 Mem_Free(fragstring);
1745         if (vertexstring)
1746                 Mem_Free(vertexstring);
1747         if (geometrystring)
1748                 Mem_Free(geometrystring);
1749         if (fragmentstring)
1750                 Mem_Free(fragmentstring);
1751 }
1752
1753 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1754 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1755 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);}
1756 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);}
1757 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);}
1758 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);}
1759
1760 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1761 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1762 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);}
1763 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);}
1764 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);}
1765 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);}
1766
1767 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1768 {
1769         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1770         if (r_hlsl_permutation != perm)
1771         {
1772                 r_hlsl_permutation = perm;
1773                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1774                 {
1775                         if (!r_hlsl_permutation->compiled)
1776                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1777                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1778                         {
1779                                 // remove features until we find a valid permutation
1780                                 int i;
1781                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1782                                 {
1783                                         // reduce i more quickly whenever it would not remove any bits
1784                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1785                                         if (!(permutation & j))
1786                                                 continue;
1787                                         permutation -= j;
1788                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1789                                         if (!r_hlsl_permutation->compiled)
1790                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1791                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1792                                                 break;
1793                                 }
1794                                 if (i >= SHADERPERMUTATION_COUNT)
1795                                 {
1796                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1797                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1798                                         return; // no bit left to clear, entire mode is broken
1799                                 }
1800                         }
1801                 }
1802                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1803                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1804         }
1805         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1806         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1807         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1808 }
1809 #endif
1810
1811 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1812 {
1813         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1814         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1815         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1816         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1817 }
1818
1819 void R_GLSL_Restart_f(void)
1820 {
1821         unsigned int i, limit;
1822         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1823                 Mem_Free(glslshaderstring);
1824         glslshaderstring = NULL;
1825         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1826                 Mem_Free(hlslshaderstring);
1827         hlslshaderstring = NULL;
1828         switch(vid.renderpath)
1829         {
1830         case RENDERPATH_D3D9:
1831 #ifdef SUPPORTD3D
1832                 {
1833                         r_hlsl_permutation_t *p;
1834                         r_hlsl_permutation = NULL;
1835                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1836                         for (i = 0;i < limit;i++)
1837                         {
1838                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1839                                 {
1840                                         if (p->vertexshader)
1841                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1842                                         if (p->pixelshader)
1843                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1844                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1845                                 }
1846                         }
1847                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1848                 }
1849 #endif
1850                 break;
1851         case RENDERPATH_D3D10:
1852                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1853                 break;
1854         case RENDERPATH_D3D11:
1855                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1856                 break;
1857         case RENDERPATH_GL20:
1858         case RENDERPATH_GLES2:
1859                 {
1860                         r_glsl_permutation_t *p;
1861                         r_glsl_permutation = NULL;
1862                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1863                         for (i = 0;i < limit;i++)
1864                         {
1865                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1866                                 {
1867                                         GL_Backend_FreeProgram(p->program);
1868                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1869                                 }
1870                         }
1871                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1872                 }
1873                 break;
1874         case RENDERPATH_GL11:
1875         case RENDERPATH_GL13:
1876         case RENDERPATH_GLES1:
1877                 break;
1878         case RENDERPATH_SOFT:
1879                 break;
1880         }
1881 }
1882
1883 static void R_GLSL_DumpShader_f(void)
1884 {
1885         int i;
1886         qfile_t *file;
1887
1888         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1889         if (file)
1890         {
1891                 FS_Print(file, "/* The engine may define the following macros:\n");
1892                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1893                 for (i = 0;i < SHADERMODE_COUNT;i++)
1894                         FS_Print(file, glslshadermodeinfo[i].pretext);
1895                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1896                         FS_Print(file, shaderpermutationinfo[i].pretext);
1897                 FS_Print(file, "*/\n");
1898                 FS_Print(file, builtinshaderstring);
1899                 FS_Close(file);
1900                 Con_Printf("glsl/default.glsl written\n");
1901         }
1902         else
1903                 Con_Printf("failed to write to glsl/default.glsl\n");
1904
1905         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1906         if (file)
1907         {
1908                 FS_Print(file, "/* The engine may define the following macros:\n");
1909                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1910                 for (i = 0;i < SHADERMODE_COUNT;i++)
1911                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1912                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1913                         FS_Print(file, shaderpermutationinfo[i].pretext);
1914                 FS_Print(file, "*/\n");
1915                 FS_Print(file, builtinhlslshaderstring);
1916                 FS_Close(file);
1917                 Con_Printf("hlsl/default.hlsl written\n");
1918         }
1919         else
1920                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1921 }
1922
1923 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1924 {
1925         unsigned int permutation = 0;
1926         if (r_trippy.integer && !notrippy)
1927                 permutation |= SHADERPERMUTATION_TRIPPY;
1928         permutation |= SHADERPERMUTATION_VIEWTINT;
1929         if (first)
1930                 permutation |= SHADERPERMUTATION_DIFFUSE;
1931         if (second)
1932                 permutation |= SHADERPERMUTATION_SPECULAR;
1933         if (texturemode == GL_MODULATE)
1934                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1935         else if (texturemode == GL_ADD)
1936                 permutation |= SHADERPERMUTATION_GLOW;
1937         else if (texturemode == GL_DECAL)
1938                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1939         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1940                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1941         if (suppresstexalpha)
1942                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1943         if (!second)
1944                 texturemode = GL_MODULATE;
1945         if (vid.allowalphatocoverage)
1946                 GL_AlphaToCoverage(false);
1947         switch (vid.renderpath)
1948         {
1949         case RENDERPATH_D3D9:
1950 #ifdef SUPPORTD3D
1951                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1952                 R_Mesh_TexBind(GL20TU_FIRST , first );
1953                 R_Mesh_TexBind(GL20TU_SECOND, second);
1954                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1955                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1956 #endif
1957                 break;
1958         case RENDERPATH_D3D10:
1959                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1960                 break;
1961         case RENDERPATH_D3D11:
1962                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1963                 break;
1964         case RENDERPATH_GL20:
1965         case RENDERPATH_GLES2:
1966                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1967                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1968                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1969                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1970                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1971                 break;
1972         case RENDERPATH_GL13:
1973         case RENDERPATH_GLES1:
1974                 R_Mesh_TexBind(0, first );
1975                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1976                 R_Mesh_TexBind(1, second);
1977                 if (second)
1978                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1979                 break;
1980         case RENDERPATH_GL11:
1981                 R_Mesh_TexBind(0, first );
1982                 break;
1983         case RENDERPATH_SOFT:
1984                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1985                 R_Mesh_TexBind(GL20TU_FIRST , first );
1986                 R_Mesh_TexBind(GL20TU_SECOND, second);
1987                 break;
1988         }
1989 }
1990
1991 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1992 {
1993         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1994 }
1995
1996 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1997 {
1998         unsigned int permutation = 0;
1999         if (r_trippy.integer && !notrippy)
2000                 permutation |= SHADERPERMUTATION_TRIPPY;
2001         if (depthrgb)
2002                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2003         if (vid.allowalphatocoverage)
2004                 GL_AlphaToCoverage(false);
2005         switch (vid.renderpath)
2006         {
2007         case RENDERPATH_D3D9:
2008 #ifdef SUPPORTD3D
2009                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2010 #endif
2011                 break;
2012         case RENDERPATH_D3D10:
2013                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2014                 break;
2015         case RENDERPATH_D3D11:
2016                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2017                 break;
2018         case RENDERPATH_GL20:
2019         case RENDERPATH_GLES2:
2020                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2021                 break;
2022         case RENDERPATH_GL13:
2023         case RENDERPATH_GLES1:
2024                 R_Mesh_TexBind(0, 0);
2025                 R_Mesh_TexBind(1, 0);
2026                 break;
2027         case RENDERPATH_GL11:
2028                 R_Mesh_TexBind(0, 0);
2029                 break;
2030         case RENDERPATH_SOFT:
2031                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2032                 break;
2033         }
2034 }
2035
2036 void R_SetupShader_ShowDepth(qboolean notrippy)
2037 {
2038         int permutation = 0;
2039         if (r_trippy.integer && !notrippy)
2040                 permutation |= SHADERPERMUTATION_TRIPPY;
2041         if (vid.allowalphatocoverage)
2042                 GL_AlphaToCoverage(false);
2043         switch (vid.renderpath)
2044         {
2045         case RENDERPATH_D3D9:
2046 #ifdef SUPPORTHLSL
2047                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2048 #endif
2049                 break;
2050         case RENDERPATH_D3D10:
2051                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2052                 break;
2053         case RENDERPATH_D3D11:
2054                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2055                 break;
2056         case RENDERPATH_GL20:
2057         case RENDERPATH_GLES2:
2058                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2059                 break;
2060         case RENDERPATH_GL13:
2061         case RENDERPATH_GLES1:
2062                 break;
2063         case RENDERPATH_GL11:
2064                 break;
2065         case RENDERPATH_SOFT:
2066                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2067                 break;
2068         }
2069 }
2070
2071 extern qboolean r_shadow_usingdeferredprepass;
2072 extern rtexture_t *r_shadow_attenuationgradienttexture;
2073 extern rtexture_t *r_shadow_attenuation2dtexture;
2074 extern rtexture_t *r_shadow_attenuation3dtexture;
2075 extern qboolean r_shadow_usingshadowmap2d;
2076 extern qboolean r_shadow_usingshadowmaportho;
2077 extern float r_shadow_shadowmap_texturescale[2];
2078 extern float r_shadow_shadowmap_parameters[4];
2079 extern qboolean r_shadow_shadowmapvsdct;
2080 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2081 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2082 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2083 extern matrix4x4_t r_shadow_shadowmapmatrix;
2084 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2085 extern int r_shadow_prepass_width;
2086 extern int r_shadow_prepass_height;
2087 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2088 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2089 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2090 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2091
2092 #define BLENDFUNC_ALLOWS_COLORMOD      1
2093 #define BLENDFUNC_ALLOWS_FOG           2
2094 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2095 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2096 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2097 static int R_BlendFuncFlags(int src, int dst)
2098 {
2099         int r = 0;
2100
2101         // a blendfunc allows colormod if:
2102         // a) it can never keep the destination pixel invariant, or
2103         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2104         // this is to prevent unintended side effects from colormod
2105
2106         // a blendfunc allows fog if:
2107         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2108         // this is to prevent unintended side effects from fog
2109
2110         // these checks are the output of fogeval.pl
2111
2112         r |= BLENDFUNC_ALLOWS_COLORMOD;
2113         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2114         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2115         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2116         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2117         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2118         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2119         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2120         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2121         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2122         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2123         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2124         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2125         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2126         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2127         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2128         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2129         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2130         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2131         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2132         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2133         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2134
2135         return r;
2136 }
2137
2138 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)
2139 {
2140         // select a permutation of the lighting shader appropriate to this
2141         // combination of texture, entity, light source, and fogging, only use the
2142         // minimum features necessary to avoid wasting rendering time in the
2143         // fragment shader on features that are not being used
2144         unsigned int permutation = 0;
2145         unsigned int mode = 0;
2146         int blendfuncflags;
2147         static float dummy_colormod[3] = {1, 1, 1};
2148         float *colormod = rsurface.colormod;
2149         float m16f[16];
2150         matrix4x4_t tempmatrix;
2151         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2152         if (rsurface.entityskeletaltransform3x4)
2153                 permutation |= SHADERPERMUTATION_SKELETAL;
2154         if (r_trippy.integer && !notrippy)
2155                 permutation |= SHADERPERMUTATION_TRIPPY;
2156         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2157                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2158         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2159                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2160         if (rsurfacepass == RSURFPASS_BACKGROUND)
2161         {
2162                 // distorted background
2163                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2164                 {
2165                         mode = SHADERMODE_WATER;
2166                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2167                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2168                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2169                         {
2170                                 // this is the right thing to do for wateralpha
2171                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2172                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2173                         }
2174                         else
2175                         {
2176                                 // this is the right thing to do for entity alpha
2177                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2178                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2179                         }
2180                 }
2181                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2182                 {
2183                         mode = SHADERMODE_REFRACTION;
2184                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2185                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2186                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2187                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2188                 }
2189                 else
2190                 {
2191                         mode = SHADERMODE_GENERIC;
2192                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2193                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2194                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2195                 }
2196                 if (vid.allowalphatocoverage)
2197                         GL_AlphaToCoverage(false);
2198         }
2199         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2200         {
2201                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2202                 {
2203                         switch(rsurface.texture->offsetmapping)
2204                         {
2205                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2206                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2207                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2208                         case OFFSETMAPPING_OFF: break;
2209                         }
2210                 }
2211                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2212                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2213                 // normalmap (deferred prepass), may use alpha test on diffuse
2214                 mode = SHADERMODE_DEFERREDGEOMETRY;
2215                 GL_BlendFunc(GL_ONE, GL_ZERO);
2216                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2217                 if (vid.allowalphatocoverage)
2218                         GL_AlphaToCoverage(false);
2219         }
2220         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2221         {
2222                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2223                 {
2224                         switch(rsurface.texture->offsetmapping)
2225                         {
2226                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2227                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2228                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2229                         case OFFSETMAPPING_OFF: break;
2230                         }
2231                 }
2232                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2233                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2234                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2235                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2236                 // light source
2237                 mode = SHADERMODE_LIGHTSOURCE;
2238                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2239                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2240                 if (diffusescale > 0)
2241                         permutation |= SHADERPERMUTATION_DIFFUSE;
2242                 if (specularscale > 0)
2243                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2244                 if (r_refdef.fogenabled)
2245                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2246                 if (rsurface.texture->colormapping)
2247                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2248                 if (r_shadow_usingshadowmap2d)
2249                 {
2250                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2251                         if(r_shadow_shadowmapvsdct)
2252                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2253
2254                         if (r_shadow_shadowmap2ddepthbuffer)
2255                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2256                 }
2257                 if (rsurface.texture->reflectmasktexture)
2258                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2259                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2260                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2261                 if (vid.allowalphatocoverage)
2262                         GL_AlphaToCoverage(false);
2263         }
2264         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2265         {
2266                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2267                 {
2268                         switch(rsurface.texture->offsetmapping)
2269                         {
2270                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2271                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2272                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2273                         case OFFSETMAPPING_OFF: break;
2274                         }
2275                 }
2276                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2277                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2278                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2279                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2280                 // unshaded geometry (fullbright or ambient model lighting)
2281                 mode = SHADERMODE_FLATCOLOR;
2282                 ambientscale = diffusescale = specularscale = 0;
2283                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2284                         permutation |= SHADERPERMUTATION_GLOW;
2285                 if (r_refdef.fogenabled)
2286                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2287                 if (rsurface.texture->colormapping)
2288                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2289                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2290                 {
2291                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2292                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2293
2294                         if (r_shadow_shadowmap2ddepthbuffer)
2295                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2296                 }
2297                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2298                         permutation |= SHADERPERMUTATION_REFLECTION;
2299                 if (rsurface.texture->reflectmasktexture)
2300                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2301                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2302                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2303                 // when using alphatocoverage, we don't need alphakill
2304                 if (vid.allowalphatocoverage)
2305                 {
2306                         if (r_transparent_alphatocoverage.integer)
2307                         {
2308                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2309                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2310                         }
2311                         else
2312                                 GL_AlphaToCoverage(false);
2313                 }
2314         }
2315         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2316         {
2317                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2318                 {
2319                         switch(rsurface.texture->offsetmapping)
2320                         {
2321                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2322                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2323                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2324                         case OFFSETMAPPING_OFF: break;
2325                         }
2326                 }
2327                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2328                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2329                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2330                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2331                 // directional model lighting
2332                 mode = SHADERMODE_LIGHTDIRECTION;
2333                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2334                         permutation |= SHADERPERMUTATION_GLOW;
2335                 permutation |= SHADERPERMUTATION_DIFFUSE;
2336                 if (specularscale > 0)
2337                         permutation |= SHADERPERMUTATION_SPECULAR;
2338                 if (r_refdef.fogenabled)
2339                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2340                 if (rsurface.texture->colormapping)
2341                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2342                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2343                 {
2344                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2345                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2346
2347                         if (r_shadow_shadowmap2ddepthbuffer)
2348                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2349                 }
2350                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2351                         permutation |= SHADERPERMUTATION_REFLECTION;
2352                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2353                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2354                 if (rsurface.texture->reflectmasktexture)
2355                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2356                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2357                 {
2358                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2359                         if (r_shadow_bouncegriddirectional)
2360                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2361                 }
2362                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2363                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2364                 // when using alphatocoverage, we don't need alphakill
2365                 if (vid.allowalphatocoverage)
2366                 {
2367                         if (r_transparent_alphatocoverage.integer)
2368                         {
2369                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2370                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2371                         }
2372                         else
2373                                 GL_AlphaToCoverage(false);
2374                 }
2375         }
2376         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2377         {
2378                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2379                 {
2380                         switch(rsurface.texture->offsetmapping)
2381                         {
2382                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2383                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2384                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2385                         case OFFSETMAPPING_OFF: break;
2386                         }
2387                 }
2388                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2389                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2390                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2391                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2392                 // ambient model lighting
2393                 mode = SHADERMODE_LIGHTDIRECTION;
2394                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2395                         permutation |= SHADERPERMUTATION_GLOW;
2396                 if (r_refdef.fogenabled)
2397                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2398                 if (rsurface.texture->colormapping)
2399                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2400                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2401                 {
2402                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2403                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2404
2405                         if (r_shadow_shadowmap2ddepthbuffer)
2406                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2407                 }
2408                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2409                         permutation |= SHADERPERMUTATION_REFLECTION;
2410                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2411                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2412                 if (rsurface.texture->reflectmasktexture)
2413                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2414                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2415                 {
2416                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2417                         if (r_shadow_bouncegriddirectional)
2418                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2419                 }
2420                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2421                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2422                 // when using alphatocoverage, we don't need alphakill
2423                 if (vid.allowalphatocoverage)
2424                 {
2425                         if (r_transparent_alphatocoverage.integer)
2426                         {
2427                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2428                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2429                         }
2430                         else
2431                                 GL_AlphaToCoverage(false);
2432                 }
2433         }
2434         else
2435         {
2436                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2437                 {
2438                         switch(rsurface.texture->offsetmapping)
2439                         {
2440                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2441                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2442                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2443                         case OFFSETMAPPING_OFF: break;
2444                         }
2445                 }
2446                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2447                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2448                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2449                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2450                 // lightmapped wall
2451                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2452                         permutation |= SHADERPERMUTATION_GLOW;
2453                 if (r_refdef.fogenabled)
2454                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2455                 if (rsurface.texture->colormapping)
2456                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2457                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2458                 {
2459                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2460                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2461
2462                         if (r_shadow_shadowmap2ddepthbuffer)
2463                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2464                 }
2465                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2466                         permutation |= SHADERPERMUTATION_REFLECTION;
2467                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2468                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2469                 if (rsurface.texture->reflectmasktexture)
2470                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2471                 if (FAKELIGHT_ENABLED)
2472                 {
2473                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2474                         mode = SHADERMODE_FAKELIGHT;
2475                         permutation |= SHADERPERMUTATION_DIFFUSE;
2476                         if (specularscale > 0)
2477                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2478                 }
2479                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2480                 {
2481                         // deluxemapping (light direction texture)
2482                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2483                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2484                         else
2485                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2486                         permutation |= SHADERPERMUTATION_DIFFUSE;
2487                         if (specularscale > 0)
2488                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2489                 }
2490                 else if (r_glsl_deluxemapping.integer >= 2)
2491                 {
2492                         // fake deluxemapping (uniform light direction in tangentspace)
2493                         if (rsurface.uselightmaptexture)
2494                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2495                         else
2496                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2497                         permutation |= SHADERPERMUTATION_DIFFUSE;
2498                         if (specularscale > 0)
2499                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2500                 }
2501                 else if (rsurface.uselightmaptexture)
2502                 {
2503                         // ordinary lightmapping (q1bsp, q3bsp)
2504                         mode = SHADERMODE_LIGHTMAP;
2505                 }
2506                 else
2507                 {
2508                         // ordinary vertex coloring (q3bsp)
2509                         mode = SHADERMODE_VERTEXCOLOR;
2510                 }
2511                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2512                 {
2513                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2514                         if (r_shadow_bouncegriddirectional)
2515                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2516                 }
2517                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2518                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2519                 // when using alphatocoverage, we don't need alphakill
2520                 if (vid.allowalphatocoverage)
2521                 {
2522                         if (r_transparent_alphatocoverage.integer)
2523                         {
2524                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2525                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2526                         }
2527                         else
2528                                 GL_AlphaToCoverage(false);
2529                 }
2530         }
2531         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2532                 colormod = dummy_colormod;
2533         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2534                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2535         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2536                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2537         switch(vid.renderpath)
2538         {
2539         case RENDERPATH_D3D9:
2540 #ifdef SUPPORTD3D
2541                 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);
2542                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2543                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2544                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2545                 if (mode == SHADERMODE_LIGHTSOURCE)
2546                 {
2547                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2548                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2549                 }
2550                 else
2551                 {
2552                         if (mode == SHADERMODE_LIGHTDIRECTION)
2553                         {
2554                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2555                         }
2556                 }
2557                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2558                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2559                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2560                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2561                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2562
2563                 if (mode == SHADERMODE_LIGHTSOURCE)
2564                 {
2565                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2566                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2567                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2568                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2569                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2570
2571                         // additive passes are only darkened by fog, not tinted
2572                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2573                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2574                 }
2575                 else
2576                 {
2577                         if (mode == SHADERMODE_FLATCOLOR)
2578                         {
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2580                         }
2581                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2582                         {
2583                                 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]);
2584                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2585                                 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);
2586                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2587                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2588                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2589                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2590                         }
2591                         else
2592                         {
2593                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2594                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2595                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2596                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2597                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2598                         }
2599                         // additive passes are only darkened by fog, not tinted
2600                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2601                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2602                         else
2603                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2604                         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);
2605                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2606                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2607                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2608                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2609                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2610                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2611                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2612                         if (mode == SHADERMODE_WATER)
2613                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2614                 }
2615                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2616                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2617                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2618                 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));
2619                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2620                 if (rsurface.texture->pantstexture)
2621                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2622                 else
2623                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2624                 if (rsurface.texture->shirttexture)
2625                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2626                 else
2627                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2628                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2629                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2630                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2631                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2632                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2633                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2634                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2635                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2636                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2637                         );
2638                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2639                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2640                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2641                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2642
2643                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2644                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2645                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2646                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2647                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2648                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2649                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2650                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2651                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2652                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2653                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2654                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2655                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2656                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2657                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2658                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2659                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2660                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2661                 {
2662                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2663                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2664                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2665                 }
2666                 else
2667                 {
2668                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2669                 }
2670 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2671                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2672                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2673                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2674                 {
2675                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2676                         if (rsurface.rtlight)
2677                         {
2678                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2679                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2680                         }
2681                 }
2682 #endif
2683                 break;
2684         case RENDERPATH_D3D10:
2685                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2686                 break;
2687         case RENDERPATH_D3D11:
2688                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2689                 break;
2690         case RENDERPATH_GL20:
2691         case RENDERPATH_GLES2:
2692                 if (!vid.useinterleavedarrays)
2693                 {
2694                         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);
2695                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2696                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2697                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2698                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2699                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2700                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2701                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2702                         R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
2703                         R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(unsigned char[4]), rsurface.batchskeletalindex4ub, rsurface.batchskeletalindex4ub_vertexbuffer, rsurface.batchskeletalindex4ub_bufferoffset);
2704                         R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), rsurface.batchskeletalweight4ub, rsurface.batchskeletalweight4ub_vertexbuffer, rsurface.batchskeletalweight4ub_bufferoffset);
2705                 }
2706                 else
2707                 {
2708                         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);
2709                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2710                 }
2711                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2712                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2713                 if (mode == SHADERMODE_LIGHTSOURCE)
2714                 {
2715                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2716                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2717                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2718                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2719                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2720                         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);
2721         
2722                         // additive passes are only darkened by fog, not tinted
2723                         if (r_glsl_permutation->loc_FogColor >= 0)
2724                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2725                         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);
2726                 }
2727                 else
2728                 {
2729                         if (mode == SHADERMODE_FLATCOLOR)
2730                         {
2731                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2732                         }
2733                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2734                         {
2735                                 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]);
2736                                 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]);
2737                                 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);
2738                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2739                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2740                                 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]);
2741                                 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]);
2742                         }
2743                         else
2744                         {
2745                                 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]);
2746                                 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]);
2747                                 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);
2748                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2749                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2750                         }
2751                         // additive passes are only darkened by fog, not tinted
2752                         if (r_glsl_permutation->loc_FogColor >= 0)
2753                         {
2754                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2755                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2756                                 else
2757                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2758                         }
2759                         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);
2760                         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]);
2761                         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]);
2762                         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]);
2763                         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]);
2764                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2765                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2766                         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);
2767                         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]);
2768                 }
2769                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2770                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2771                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2772                 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]);
2773                 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]);
2774
2775                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2776                 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));
2777                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2778                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2779                 {
2780                         if (rsurface.texture->pantstexture)
2781                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2782                         else
2783                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2784                 }
2785                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2786                 {
2787                         if (rsurface.texture->shirttexture)
2788                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2789                         else
2790                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2791                 }
2792                 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]);
2793                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2794                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2795                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2796                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2797                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2798                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2799                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2800                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2801                         );
2802                 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);
2803                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2804                 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]);
2805                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2806                 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);}
2807                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2808
2809                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2810                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2811                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2812                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2813                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2814                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2815                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2816                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2817                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2818                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2819                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2820                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2821                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2822                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2823                 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);
2824                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2825                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2826                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2827                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2828                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2829                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2830                 {
2831                         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);
2832                         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);
2833                         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);
2834                 }
2835                 else
2836                 {
2837                         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);
2838                 }
2839                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2840                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2841                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2842                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2843                 {
2844                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2845                         if (rsurface.rtlight)
2846                         {
2847                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2848                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2849                         }
2850                 }
2851                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2852                 if (r_glsl_permutation->loc_Skeletal_Transform12 >= 0 && rsurface.entityskeletalnumtransforms > 0)
2853                         qglUniform4fv(r_glsl_permutation->loc_Skeletal_Transform12, rsurface.entityskeletalnumtransforms*3, rsurface.entityskeletaltransform3x4);
2854                 CHECKGLERROR
2855                 break;
2856         case RENDERPATH_GL11:
2857         case RENDERPATH_GL13:
2858         case RENDERPATH_GLES1:
2859                 break;
2860         case RENDERPATH_SOFT:
2861                 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);
2862                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2863                 R_SetupShader_SetPermutationSoft(mode, permutation);
2864                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2865                 if (mode == SHADERMODE_LIGHTSOURCE)
2866                 {
2867                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2868                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2869                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2870                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2871                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2872                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2873         
2874                         // additive passes are only darkened by fog, not tinted
2875                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2876                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2877                 }
2878                 else
2879                 {
2880                         if (mode == SHADERMODE_FLATCOLOR)
2881                         {
2882                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2883                         }
2884                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2885                         {
2886                                 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]);
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2888                                 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);
2889                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2890                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2891                                 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]);
2892                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2893                         }
2894                         else
2895                         {
2896                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2897                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2898                                 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);
2899                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2900                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2901                         }
2902                         // additive passes are only darkened by fog, not tinted
2903                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2904                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2905                         else
2906                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2907                         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);
2908                         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]);
2909                         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]);
2910                         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]);
2911                         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]);
2912                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2913                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2914                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2915                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2916                 }
2917                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2918                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2919                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2920                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2921                 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]);
2922
2923                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2924                 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));
2925                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2926                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2927                 {
2928                         if (rsurface.texture->pantstexture)
2929                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2930                         else
2931                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2932                 }
2933                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2934                 {
2935                         if (rsurface.texture->shirttexture)
2936                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2937                         else
2938                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2939                 }
2940                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2941                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2942                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2943                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2944                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2945                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2946                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2947                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2948                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2949                         );
2950                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2951                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2952                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2953                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2954
2955                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2956                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2957                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2958                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2959                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2960                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2961                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2962                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2963                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2964                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2965                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2966                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2967                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2968                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2969                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2970                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2971                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2972                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2973                 {
2974                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2975                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2976                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2977                 }
2978                 else
2979                 {
2980                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2981                 }
2982 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2983                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2984                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2985                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2986                 {
2987                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2988                         if (rsurface.rtlight)
2989                         {
2990                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2991                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2992                         }
2993                 }
2994                 break;
2995         }
2996 }
2997
2998 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2999 {
3000         // select a permutation of the lighting shader appropriate to this
3001         // combination of texture, entity, light source, and fogging, only use the
3002         // minimum features necessary to avoid wasting rendering time in the
3003         // fragment shader on features that are not being used
3004         unsigned int permutation = 0;
3005         unsigned int mode = 0;
3006         const float *lightcolorbase = rtlight->currentcolor;
3007         float ambientscale = rtlight->ambientscale;
3008         float diffusescale = rtlight->diffusescale;
3009         float specularscale = rtlight->specularscale;
3010         // this is the location of the light in view space
3011         vec3_t viewlightorigin;
3012         // this transforms from view space (camera) to light space (cubemap)
3013         matrix4x4_t viewtolight;
3014         matrix4x4_t lighttoview;
3015         float viewtolight16f[16];
3016         // light source
3017         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3018         if (rtlight->currentcubemap != r_texture_whitecube)
3019                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3020         if (diffusescale > 0)
3021                 permutation |= SHADERPERMUTATION_DIFFUSE;
3022         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3023                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3024         if (r_shadow_usingshadowmap2d)
3025         {
3026                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3027                 if (r_shadow_shadowmapvsdct)
3028                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3029
3030                 if (r_shadow_shadowmap2ddepthbuffer)
3031                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3032         }
3033         if (vid.allowalphatocoverage)
3034                 GL_AlphaToCoverage(false);
3035         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3036         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3037         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3038         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3039         switch(vid.renderpath)
3040         {
3041         case RENDERPATH_D3D9:
3042 #ifdef SUPPORTD3D
3043                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3044                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3045                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3046                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3047                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3048                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3049                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3050                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3051                 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);
3052                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3053                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3054
3055                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3056                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3057                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3058                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3059                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3060 #endif
3061                 break;
3062         case RENDERPATH_D3D10:
3063                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3064                 break;
3065         case RENDERPATH_D3D11:
3066                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3067                 break;
3068         case RENDERPATH_GL20:
3069         case RENDERPATH_GLES2:
3070                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3071                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3072                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3073                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3074                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3075                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3076                 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]);
3077                 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]);
3078                 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);
3079                 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]);
3080                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3081
3082                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3083                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3084                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3085                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3086                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3087                 break;
3088         case RENDERPATH_GL11:
3089         case RENDERPATH_GL13:
3090         case RENDERPATH_GLES1:
3091                 break;
3092         case RENDERPATH_SOFT:
3093                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3094                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3095                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3096                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3097                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3098                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3099                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3100                 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]);
3101                 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);
3102                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3103                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3104
3105                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3106                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3107                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3108                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3109                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3110                 break;
3111         }
3112 }
3113
3114 #define SKINFRAME_HASH 1024
3115
3116 typedef struct
3117 {
3118         int loadsequence; // incremented each level change
3119         memexpandablearray_t array;
3120         skinframe_t *hash[SKINFRAME_HASH];
3121 }
3122 r_skinframe_t;
3123 r_skinframe_t r_skinframe;
3124
3125 void R_SkinFrame_PrepareForPurge(void)
3126 {
3127         r_skinframe.loadsequence++;
3128         // wrap it without hitting zero
3129         if (r_skinframe.loadsequence >= 200)
3130                 r_skinframe.loadsequence = 1;
3131 }
3132
3133 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3134 {
3135         if (!skinframe)
3136                 return;
3137         // mark the skinframe as used for the purging code
3138         skinframe->loadsequence = r_skinframe.loadsequence;
3139 }
3140
3141 void R_SkinFrame_Purge(void)
3142 {
3143         int i;
3144         skinframe_t *s;
3145         for (i = 0;i < SKINFRAME_HASH;i++)
3146         {
3147                 for (s = r_skinframe.hash[i];s;s = s->next)
3148                 {
3149                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3150                         {
3151                                 if (s->merged == s->base)
3152                                         s->merged = NULL;
3153                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3154                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3155                                 R_PurgeTexture(s->merged);s->merged = NULL;
3156                                 R_PurgeTexture(s->base  );s->base   = NULL;
3157                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3158                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3159                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3160                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3161                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3162                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3163                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3164                                 s->loadsequence = 0;
3165                         }
3166                 }
3167         }
3168 }
3169
3170 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3171         skinframe_t *item;
3172         char basename[MAX_QPATH];
3173
3174         Image_StripImageExtension(name, basename, sizeof(basename));
3175
3176         if( last == NULL ) {
3177                 int hashindex;
3178                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3179                 item = r_skinframe.hash[hashindex];
3180         } else {
3181                 item = last->next;
3182         }
3183
3184         // linearly search through the hash bucket
3185         for( ; item ; item = item->next ) {
3186                 if( !strcmp( item->basename, basename ) ) {
3187                         return item;
3188                 }
3189         }
3190         return NULL;
3191 }
3192
3193 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3194 {
3195         skinframe_t *item;
3196         int hashindex;
3197         char basename[MAX_QPATH];
3198
3199         Image_StripImageExtension(name, basename, sizeof(basename));
3200
3201         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3202         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3203                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3204                         break;
3205
3206         if (!item) {
3207                 rtexture_t *dyntexture;
3208                 // check whether its a dynamic texture
3209                 dyntexture = CL_GetDynTexture( basename );
3210                 if (!add && !dyntexture)
3211                         return NULL;
3212                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3213                 memset(item, 0, sizeof(*item));
3214                 strlcpy(item->basename, basename, sizeof(item->basename));
3215                 item->base = dyntexture; // either NULL or dyntexture handle
3216                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3217                 item->comparewidth = comparewidth;
3218                 item->compareheight = compareheight;
3219                 item->comparecrc = comparecrc;
3220                 item->next = r_skinframe.hash[hashindex];
3221                 r_skinframe.hash[hashindex] = item;
3222         }
3223         else if (textureflags & TEXF_FORCE_RELOAD)
3224         {
3225                 rtexture_t *dyntexture;
3226                 // check whether its a dynamic texture
3227                 dyntexture = CL_GetDynTexture( basename );
3228                 if (!add && !dyntexture)
3229                         return NULL;
3230                 if (item->merged == item->base)
3231                         item->merged = NULL;
3232                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3233                 R_PurgeTexture(item->stain );item->stain  = NULL;
3234                 R_PurgeTexture(item->merged);item->merged = NULL;
3235                 R_PurgeTexture(item->base  );item->base   = NULL;
3236                 R_PurgeTexture(item->pants );item->pants  = NULL;
3237                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3238                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3239                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3240                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3241                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3242         R_PurgeTexture(item->reflect);item->reflect = NULL;
3243                 item->loadsequence = 0;
3244         }
3245         else if( item->base == NULL )
3246         {
3247                 rtexture_t *dyntexture;
3248                 // check whether its a dynamic texture
3249                 // 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]
3250                 dyntexture = CL_GetDynTexture( basename );
3251                 item->base = dyntexture; // either NULL or dyntexture handle
3252         }
3253
3254         R_SkinFrame_MarkUsed(item);
3255         return item;
3256 }
3257
3258 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3259         { \
3260                 unsigned long long avgcolor[5], wsum; \
3261                 int pix, comp, w; \
3262                 avgcolor[0] = 0; \
3263                 avgcolor[1] = 0; \
3264                 avgcolor[2] = 0; \
3265                 avgcolor[3] = 0; \
3266                 avgcolor[4] = 0; \
3267                 wsum = 0; \
3268                 for(pix = 0; pix < cnt; ++pix) \
3269                 { \
3270                         w = 0; \
3271                         for(comp = 0; comp < 3; ++comp) \
3272                                 w += getpixel; \
3273                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3274                         { \
3275                                 ++wsum; \
3276                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3277                                 w = getpixel; \
3278                                 for(comp = 0; comp < 3; ++comp) \
3279                                         avgcolor[comp] += getpixel * w; \
3280                                 avgcolor[3] += w; \
3281                         } \
3282                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3283                         avgcolor[4] += getpixel; \
3284                 } \
3285                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3286                         avgcolor[3] = 1; \
3287                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3288                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3289                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3290                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3291         }
3292
3293 extern cvar_t gl_picmip;
3294 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3295 {
3296         int j;
3297         unsigned char *pixels;
3298         unsigned char *bumppixels;
3299         unsigned char *basepixels = NULL;
3300         int basepixels_width = 0;
3301         int basepixels_height = 0;
3302         skinframe_t *skinframe;
3303         rtexture_t *ddsbase = NULL;
3304         qboolean ddshasalpha = false;
3305         float ddsavgcolor[4];
3306         char basename[MAX_QPATH];
3307         int miplevel = R_PicmipForFlags(textureflags);
3308         int savemiplevel = miplevel;
3309         int mymiplevel;
3310         char vabuf[1024];
3311
3312         if (cls.state == ca_dedicated)
3313                 return NULL;
3314
3315         // return an existing skinframe if already loaded
3316         // if loading of the first image fails, don't make a new skinframe as it
3317         // would cause all future lookups of this to be missing
3318         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3319         if (skinframe && skinframe->base)
3320                 return skinframe;
3321
3322         Image_StripImageExtension(name, basename, sizeof(basename));
3323
3324         // check for DDS texture file first
3325         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3326         {
3327                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3328                 if (basepixels == NULL)
3329                         return NULL;
3330         }
3331
3332         // FIXME handle miplevel
3333
3334         if (developer_loading.integer)
3335                 Con_Printf("loading skin \"%s\"\n", name);
3336
3337         // we've got some pixels to store, so really allocate this new texture now
3338         if (!skinframe)
3339                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3340         textureflags &= ~TEXF_FORCE_RELOAD;
3341         skinframe->stain = NULL;
3342         skinframe->merged = NULL;
3343         skinframe->base = NULL;
3344         skinframe->pants = NULL;
3345         skinframe->shirt = NULL;
3346         skinframe->nmap = NULL;
3347         skinframe->gloss = NULL;
3348         skinframe->glow = NULL;
3349         skinframe->fog = NULL;
3350         skinframe->reflect = NULL;
3351         skinframe->hasalpha = false;
3352
3353         if (ddsbase)
3354         {
3355                 skinframe->base = ddsbase;
3356                 skinframe->hasalpha = ddshasalpha;
3357                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3358                 if (r_loadfog && skinframe->hasalpha)
3359                         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);
3360                 //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]);
3361         }
3362         else
3363         {
3364                 basepixels_width = image_width;
3365                 basepixels_height = image_height;
3366                 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);
3367                 if (textureflags & TEXF_ALPHA)
3368                 {
3369                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3370                         {
3371                                 if (basepixels[j] < 255)
3372                                 {
3373                                         skinframe->hasalpha = true;
3374                                         break;
3375                                 }
3376                         }
3377                         if (r_loadfog && skinframe->hasalpha)
3378                         {
3379                                 // has transparent pixels
3380                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3381                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3382                                 {
3383                                         pixels[j+0] = 255;
3384                                         pixels[j+1] = 255;
3385                                         pixels[j+2] = 255;
3386                                         pixels[j+3] = basepixels[j+3];
3387                                 }
3388                                 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);
3389                                 Mem_Free(pixels);
3390                         }
3391                 }
3392                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3393 #ifndef USE_GLES2
3394                 //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]);
3395                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3396                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3397                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3398                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3399 #endif
3400         }
3401
3402         if (r_loaddds)
3403         {
3404                 mymiplevel = savemiplevel;
3405                 if (r_loadnormalmap)
3406                         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);
3407                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3408                 if (r_loadgloss)
3409                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3410                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3411                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3412                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3413         }
3414
3415         // _norm is the name used by tenebrae and has been adopted as standard
3416         if (r_loadnormalmap && skinframe->nmap == NULL)
3417         {
3418                 mymiplevel = savemiplevel;
3419                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3420                 {
3421                         skinframe->nmap = R_LoadTexture2D (r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_nmap", skinframe->basename), image_width, image_height, pixels, TEXTYPE_BGRA, (TEXF_ALPHA | textureflags) & (r_mipnormalmaps.integer ? ~0 : ~TEXF_MIPMAP) & (gl_texturecompression_normal.integer && gl_texturecompression.integer ? ~0 : ~TEXF_COMPRESS), mymiplevel, NULL);
3422                         Mem_Free(pixels);
3423                         pixels = NULL;
3424                 }
3425                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3426                 {
3427                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3428                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3429                         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);
3430                         Mem_Free(pixels);
3431                         Mem_Free(bumppixels);
3432                 }
3433                 else if (r_shadow_bumpscale_basetexture.value > 0)
3434                 {
3435                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3436                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3437                         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);
3438                         Mem_Free(pixels);
3439                 }
3440 #ifndef USE_GLES2
3441                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3442                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3443 #endif
3444         }
3445
3446         // _luma is supported only for tenebrae compatibility
3447         // _glow is the preferred name
3448         mymiplevel = savemiplevel;
3449         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))))
3450         {
3451                 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);
3452 #ifndef USE_GLES2
3453                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3454                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3455 #endif
3456                 Mem_Free(pixels);pixels = NULL;
3457         }
3458
3459         mymiplevel = savemiplevel;
3460         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3461         {
3462                 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);
3463 #ifndef USE_GLES2
3464                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3465                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3466 #endif
3467                 Mem_Free(pixels);
3468                 pixels = NULL;
3469         }
3470
3471         mymiplevel = savemiplevel;
3472         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3473         {
3474                 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);
3475 #ifndef USE_GLES2
3476                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3477                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3478 #endif
3479                 Mem_Free(pixels);
3480                 pixels = NULL;
3481         }
3482
3483         mymiplevel = savemiplevel;
3484         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3485         {
3486                 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);
3487 #ifndef USE_GLES2
3488                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3489                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3490 #endif
3491                 Mem_Free(pixels);
3492                 pixels = NULL;
3493         }
3494
3495         mymiplevel = savemiplevel;
3496         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3497         {
3498                 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);
3499 #ifndef USE_GLES2
3500                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3501                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3502 #endif
3503                 Mem_Free(pixels);
3504                 pixels = NULL;
3505         }
3506
3507         if (basepixels)
3508                 Mem_Free(basepixels);
3509
3510         return skinframe;
3511 }
3512
3513 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3514 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3515 {
3516         int i;
3517         unsigned char *temp1, *temp2;
3518         skinframe_t *skinframe;
3519         char vabuf[1024];
3520
3521         if (cls.state == ca_dedicated)
3522                 return NULL;
3523
3524         // if already loaded just return it, otherwise make a new skinframe
3525         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3526         if (skinframe->base)
3527                 return skinframe;
3528         textureflags &= ~TEXF_FORCE_RELOAD;
3529
3530         skinframe->stain = NULL;
3531         skinframe->merged = NULL;
3532         skinframe->base = NULL;
3533         skinframe->pants = NULL;
3534         skinframe->shirt = NULL;
3535         skinframe->nmap = NULL;
3536         skinframe->gloss = NULL;
3537         skinframe->glow = NULL;
3538         skinframe->fog = NULL;
3539         skinframe->reflect = NULL;
3540         skinframe->hasalpha = false;
3541
3542         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3543         if (!skindata)
3544                 return NULL;
3545
3546         if (developer_loading.integer)
3547                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3548
3549         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3550         {
3551                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3552                 temp2 = temp1 + width * height * 4;
3553                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3554                 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);
3555                 Mem_Free(temp1);
3556         }
3557         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3558         if (textureflags & TEXF_ALPHA)
3559         {
3560                 for (i = 3;i < width * height * 4;i += 4)
3561                 {
3562                         if (skindata[i] < 255)
3563                         {
3564                                 skinframe->hasalpha = true;
3565                                 break;
3566                         }
3567                 }
3568                 if (r_loadfog && skinframe->hasalpha)
3569                 {
3570                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3571                         memcpy(fogpixels, skindata, width * height * 4);
3572                         for (i = 0;i < width * height * 4;i += 4)
3573                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3574                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3575                         Mem_Free(fogpixels);
3576                 }
3577         }
3578
3579         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3580         //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]);
3581
3582         return skinframe;
3583 }
3584
3585 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3586 {
3587         int i;
3588         int featuresmask;
3589         skinframe_t *skinframe;
3590
3591         if (cls.state == ca_dedicated)
3592                 return NULL;
3593
3594         // if already loaded just return it, otherwise make a new skinframe
3595         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3596         if (skinframe->base)
3597                 return skinframe;
3598         //textureflags &= ~TEXF_FORCE_RELOAD;
3599
3600         skinframe->stain = NULL;
3601         skinframe->merged = NULL;
3602         skinframe->base = NULL;
3603         skinframe->pants = NULL;
3604         skinframe->shirt = NULL;
3605         skinframe->nmap = NULL;
3606         skinframe->gloss = NULL;
3607         skinframe->glow = NULL;
3608         skinframe->fog = NULL;
3609         skinframe->reflect = NULL;
3610         skinframe->hasalpha = false;
3611
3612         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3613         if (!skindata)
3614                 return NULL;
3615
3616         if (developer_loading.integer)
3617                 Con_Printf("loading quake skin \"%s\"\n", name);
3618
3619         // 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)
3620         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3621         memcpy(skinframe->qpixels, skindata, width*height);
3622         skinframe->qwidth = width;
3623         skinframe->qheight = height;
3624
3625         featuresmask = 0;
3626         for (i = 0;i < width * height;i++)
3627                 featuresmask |= palette_featureflags[skindata[i]];
3628
3629         skinframe->hasalpha = false;
3630         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3631         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3632         skinframe->qgeneratemerged = true;
3633         skinframe->qgeneratebase = skinframe->qhascolormapping;
3634         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3635
3636         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3637         //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]);
3638
3639         return skinframe;
3640 }
3641
3642 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3643 {
3644         int width;
3645         int height;
3646         unsigned char *skindata;
3647         char vabuf[1024];
3648
3649         if (!skinframe->qpixels)
3650                 return;
3651
3652         if (!skinframe->qhascolormapping)
3653                 colormapped = false;
3654
3655         if (colormapped)
3656         {
3657                 if (!skinframe->qgeneratebase)
3658                         return;
3659         }
3660         else
3661         {
3662                 if (!skinframe->qgeneratemerged)
3663                         return;
3664         }
3665
3666         width = skinframe->qwidth;
3667         height = skinframe->qheight;
3668         skindata = skinframe->qpixels;
3669
3670         if (skinframe->qgeneratenmap)
3671         {
3672                 unsigned char *temp1, *temp2;
3673                 skinframe->qgeneratenmap = false;
3674                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3675                 temp2 = temp1 + width * height * 4;
3676                 // use either a custom palette or the quake palette
3677                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3678                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3679                 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);
3680                 Mem_Free(temp1);
3681         }
3682
3683         if (skinframe->qgenerateglow)
3684         {
3685                 skinframe->qgenerateglow = false;
3686                 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
3687         }
3688
3689         if (colormapped)
3690         {
3691                 skinframe->qgeneratebase = false;
3692                 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);
3693                 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);
3694                 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);
3695         }
3696         else
3697         {
3698                 skinframe->qgeneratemerged = false;
3699                 skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, vid.sRGB3D ? TEXTYPE_SRGB_PALETTE : TEXTYPE_PALETTE, skinframe->textureflags, -1, skinframe->glow ? palette_bgra_nofullbrights : palette_bgra_complete);
3700         }
3701
3702         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3703         {
3704                 Mem_Free(skinframe->qpixels);
3705                 skinframe->qpixels = NULL;
3706         }
3707 }
3708
3709 skinframe_t *R_SkinFrame_LoadInternal8bit(const char *name, int textureflags, const unsigned char *skindata, int width, int height, const unsigned int *palette, const unsigned int *alphapalette)
3710 {
3711         int i;
3712         skinframe_t *skinframe;
3713         char vabuf[1024];
3714
3715         if (cls.state == ca_dedicated)
3716                 return NULL;
3717
3718         // if already loaded just return it, otherwise make a new skinframe
3719         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3720         if (skinframe->base)
3721                 return skinframe;
3722         textureflags &= ~TEXF_FORCE_RELOAD;
3723
3724         skinframe->stain = NULL;
3725         skinframe->merged = NULL;
3726         skinframe->base = NULL;
3727         skinframe->pants = NULL;
3728         skinframe->shirt = NULL;
3729         skinframe->nmap = NULL;
3730         skinframe->gloss = NULL;
3731         skinframe->glow = NULL;
3732         skinframe->fog = NULL;
3733         skinframe->reflect = NULL;
3734         skinframe->hasalpha = false;
3735
3736         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3737         if (!skindata)
3738                 return NULL;
3739
3740         if (developer_loading.integer)
3741                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3742
3743         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3744         if (textureflags & TEXF_ALPHA)
3745         {
3746                 for (i = 0;i < width * height;i++)
3747                 {
3748                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3749                         {
3750                                 skinframe->hasalpha = true;
3751                                 break;
3752                         }
3753                 }
3754                 if (r_loadfog && skinframe->hasalpha)
3755                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3756         }
3757
3758         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3759         //Con_Printf("Texture %s has average colors %f %f %f alpha %f\n", name, skinframe->avgcolor[0], skinframe->avgcolor[1], skinframe->avgcolor[2], skinframe->avgcolor[3]);
3760
3761         return skinframe;
3762 }
3763
3764 skinframe_t *R_SkinFrame_LoadMissing(void)
3765 {
3766         skinframe_t *skinframe;
3767
3768         if (cls.state == ca_dedicated)
3769                 return NULL;
3770
3771         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3772         skinframe->stain = NULL;
3773         skinframe->merged = NULL;
3774         skinframe->base = NULL;
3775         skinframe->pants = NULL;
3776         skinframe->shirt = NULL;
3777         skinframe->nmap = NULL;
3778         skinframe->gloss = NULL;
3779         skinframe->glow = NULL;
3780         skinframe->fog = NULL;
3781         skinframe->reflect = NULL;
3782         skinframe->hasalpha = false;
3783
3784         skinframe->avgcolor[0] = rand() / RAND_MAX;
3785         skinframe->avgcolor[1] = rand() / RAND_MAX;
3786         skinframe->avgcolor[2] = rand() / RAND_MAX;
3787         skinframe->avgcolor[3] = 1;
3788
3789         return skinframe;
3790 }
3791
3792 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3793 typedef struct suffixinfo_s
3794 {
3795         const char *suffix;
3796         qboolean flipx, flipy, flipdiagonal;
3797 }
3798 suffixinfo_t;
3799 static suffixinfo_t suffix[3][6] =
3800 {
3801         {
3802                 {"px",   false, false, false},
3803                 {"nx",   false, false, false},
3804                 {"py",   false, false, false},
3805                 {"ny",   false, false, false},
3806                 {"pz",   false, false, false},
3807                 {"nz",   false, false, false}
3808         },
3809         {
3810                 {"posx", false, false, false},
3811                 {"negx", false, false, false},
3812                 {"posy", false, false, false},
3813                 {"negy", false, false, false},
3814                 {"posz", false, false, false},
3815                 {"negz", false, false, false}
3816         },
3817         {
3818                 {"rt",    true, false,  true},
3819                 {"lf",   false,  true,  true},
3820                 {"ft",    true,  true, false},
3821                 {"bk",   false, false, false},
3822                 {"up",    true, false,  true},
3823                 {"dn",    true, false,  true}
3824         }
3825 };
3826
3827 static int componentorder[4] = {0, 1, 2, 3};
3828
3829 static rtexture_t *R_LoadCubemap(const char *basename)
3830 {
3831         int i, j, cubemapsize;
3832         unsigned char *cubemappixels, *image_buffer;
3833         rtexture_t *cubemaptexture;
3834         char name[256];
3835         // must start 0 so the first loadimagepixels has no requested width/height
3836         cubemapsize = 0;
3837         cubemappixels = NULL;
3838         cubemaptexture = NULL;
3839         // keep trying different suffix groups (posx, px, rt) until one loads
3840         for (j = 0;j < 3 && !cubemappixels;j++)
3841         {
3842                 // load the 6 images in the suffix group
3843                 for (i = 0;i < 6;i++)
3844                 {
3845                         // generate an image name based on the base and and suffix
3846                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3847                         // load it
3848                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3849                         {
3850                                 // an image loaded, make sure width and height are equal
3851                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3852                                 {
3853                                         // if this is the first image to load successfully, allocate the cubemap memory
3854                                         if (!cubemappixels && image_width >= 1)
3855                                         {
3856                                                 cubemapsize = image_width;
3857                                                 // note this clears to black, so unavailable sides are black
3858                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3859                                         }
3860                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3861                                         if (cubemappixels)
3862                                                 Image_CopyMux(cubemappixels+i*cubemapsize*cubemapsize*4, image_buffer, cubemapsize, cubemapsize, suffix[j][i].flipx, suffix[j][i].flipy, suffix[j][i].flipdiagonal, 4, 4, componentorder);
3863                                 }
3864                                 else
3865                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3866                                 // free the image
3867                                 Mem_Free(image_buffer);
3868                         }
3869                 }
3870         }
3871         // if a cubemap loaded, upload it
3872         if (cubemappixels)
3873         {
3874                 if (developer_loading.integer)
3875                         Con_Printf("loading cubemap \"%s\"\n", basename);
3876
3877                 cubemaptexture = R_LoadTextureCubeMap(r_main_texturepool, basename, cubemapsize, cubemappixels, vid.sRGB3D ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, (gl_texturecompression_lightcubemaps.integer && gl_texturecompression.integer ? TEXF_COMPRESS : 0) | TEXF_FORCELINEAR | TEXF_CLAMP, -1, NULL);
3878                 Mem_Free(cubemappixels);
3879         }
3880         else
3881         {
3882                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3883                 if (developer_loading.integer)
3884                 {
3885                         Con_Printf("(tried tried images ");
3886                         for (j = 0;j < 3;j++)
3887                                 for (i = 0;i < 6;i++)
3888                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3889                         Con_Print(" and was unable to find any of them).\n");
3890                 }
3891         }
3892         return cubemaptexture;
3893 }
3894
3895 rtexture_t *R_GetCubemap(const char *basename)
3896 {
3897         int i;
3898         for (i = 0;i < r_texture_numcubemaps;i++)
3899                 if (r_texture_cubemaps[i] != NULL)
3900                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3901                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3902         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3903                 return r_texture_whitecube;
3904         r_texture_numcubemaps++;
3905         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3906         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3907         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3908         return r_texture_cubemaps[i]->texture;
3909 }
3910
3911 static void R_Main_FreeViewCache(void)
3912 {
3913         if (r_refdef.viewcache.entityvisible)
3914                 Mem_Free(r_refdef.viewcache.entityvisible);
3915         if (r_refdef.viewcache.world_pvsbits)
3916                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3917         if (r_refdef.viewcache.world_leafvisible)
3918                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3919         if (r_refdef.viewcache.world_surfacevisible)
3920                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3921         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3922 }
3923
3924 static void R_Main_ResizeViewCache(void)
3925 {
3926         int numentities = r_refdef.scene.numentities;
3927         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3928         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3929         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3930         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3931         if (r_refdef.viewcache.maxentities < numentities)
3932         {
3933                 r_refdef.viewcache.maxentities = numentities;
3934                 if (r_refdef.viewcache.entityvisible)
3935                         Mem_Free(r_refdef.viewcache.entityvisible);
3936                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3937         }
3938         if (r_refdef.viewcache.world_numclusters != numclusters)
3939         {
3940                 r_refdef.viewcache.world_numclusters = numclusters;
3941                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3942                 if (r_refdef.viewcache.world_pvsbits)
3943                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3944                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3945         }
3946         if (r_refdef.viewcache.world_numleafs != numleafs)
3947         {
3948                 r_refdef.viewcache.world_numleafs = numleafs;
3949                 if (r_refdef.viewcache.world_leafvisible)
3950                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3951                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3952         }
3953         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3954         {
3955                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3956                 if (r_refdef.viewcache.world_surfacevisible)
3957                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3958                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3959         }
3960 }
3961
3962 extern rtexture_t *loadingscreentexture;
3963 static void gl_main_start(void)
3964 {
3965         loadingscreentexture = NULL;
3966         r_texture_blanknormalmap = NULL;
3967         r_texture_white = NULL;
3968         r_texture_grey128 = NULL;
3969         r_texture_black = NULL;
3970         r_texture_whitecube = NULL;
3971         r_texture_normalizationcube = NULL;
3972         r_texture_fogattenuation = NULL;
3973         r_texture_fogheighttexture = NULL;
3974         r_texture_gammaramps = NULL;
3975         r_texture_numcubemaps = 0;
3976
3977         r_loaddds = r_texture_dds_load.integer != 0;
3978         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3979
3980         switch(vid.renderpath)
3981         {
3982         case RENDERPATH_GL20:
3983         case RENDERPATH_D3D9:
3984         case RENDERPATH_D3D10:
3985         case RENDERPATH_D3D11:
3986         case RENDERPATH_SOFT:
3987         case RENDERPATH_GLES2:
3988                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3989                 Cvar_SetValueQuick(&gl_combine, 1);
3990                 Cvar_SetValueQuick(&r_glsl, 1);
3991                 r_loadnormalmap = true;
3992                 r_loadgloss = true;
3993                 r_loadfog = false;
3994                 break;
3995         case RENDERPATH_GL13:
3996         case RENDERPATH_GLES1:
3997                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3998                 Cvar_SetValueQuick(&gl_combine, 1);
3999                 Cvar_SetValueQuick(&r_glsl, 0);
4000                 r_loadnormalmap = false;
4001                 r_loadgloss = false;
4002                 r_loadfog = true;
4003                 break;
4004         case RENDERPATH_GL11:
4005                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
4006                 Cvar_SetValueQuick(&gl_combine, 0);
4007                 Cvar_SetValueQuick(&r_glsl, 0);
4008                 r_loadnormalmap = false;
4009                 r_loadgloss = false;
4010                 r_loadfog = true;
4011                 break;
4012         }
4013
4014         R_AnimCache_Free();
4015         R_FrameData_Reset();
4016
4017         r_numqueries = 0;
4018         r_maxqueries = 0;
4019         memset(r_queries, 0, sizeof(r_queries));
4020
4021         r_qwskincache = NULL;
4022         r_qwskincache_size = 0;
4023
4024         // due to caching of texture_t references, the collision cache must be reset
4025         Collision_Cache_Reset(true);
4026
4027         // set up r_skinframe loading system for textures
4028         memset(&r_skinframe, 0, sizeof(r_skinframe));
4029         r_skinframe.loadsequence = 1;
4030         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4031
4032         r_main_texturepool = R_AllocTexturePool();
4033         R_BuildBlankTextures();
4034         R_BuildNoTexture();
4035         if (vid.support.arb_texture_cube_map)
4036         {
4037                 R_BuildWhiteCube();
4038                 R_BuildNormalizationCube();
4039         }
4040         r_texture_fogattenuation = NULL;
4041         r_texture_fogheighttexture = NULL;
4042         r_texture_gammaramps = NULL;
4043         //r_texture_fogintensity = NULL;
4044         memset(&r_fb, 0, sizeof(r_fb));
4045         r_glsl_permutation = NULL;
4046         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4047         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4048         glslshaderstring = NULL;
4049 #ifdef SUPPORTD3D
4050         r_hlsl_permutation = NULL;
4051         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4052         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4053 #endif
4054         hlslshaderstring = NULL;
4055         memset(&r_svbsp, 0, sizeof (r_svbsp));
4056
4057         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4058         r_texture_numcubemaps = 0;
4059
4060         r_refdef.fogmasktable_density = 0;
4061 }
4062
4063 static void gl_main_shutdown(void)
4064 {
4065         R_AnimCache_Free();
4066         R_FrameData_Reset();
4067
4068         R_Main_FreeViewCache();
4069
4070         switch(vid.renderpath)
4071         {
4072         case RENDERPATH_GL11:
4073         case RENDERPATH_GL13:
4074         case RENDERPATH_GL20:
4075         case RENDERPATH_GLES1:
4076         case RENDERPATH_GLES2:
4077 #ifdef GL_SAMPLES_PASSED_ARB
4078                 if (r_maxqueries)
4079                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4080 #endif
4081                 break;
4082         case RENDERPATH_D3D9:
4083                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4084                 break;
4085         case RENDERPATH_D3D10:
4086                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4087                 break;
4088         case RENDERPATH_D3D11:
4089                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4090                 break;
4091         case RENDERPATH_SOFT:
4092                 break;
4093         }
4094
4095         r_numqueries = 0;
4096         r_maxqueries = 0;
4097         memset(r_queries, 0, sizeof(r_queries));
4098
4099         r_qwskincache = NULL;
4100         r_qwskincache_size = 0;
4101
4102         // clear out the r_skinframe state
4103         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4104         memset(&r_skinframe, 0, sizeof(r_skinframe));
4105
4106         if (r_svbsp.nodes)
4107                 Mem_Free(r_svbsp.nodes);
4108         memset(&r_svbsp, 0, sizeof (r_svbsp));
4109         R_FreeTexturePool(&r_main_texturepool);
4110         loadingscreentexture = NULL;
4111         r_texture_blanknormalmap = NULL;
4112         r_texture_white = NULL;
4113         r_texture_grey128 = NULL;
4114         r_texture_black = NULL;
4115         r_texture_whitecube = NULL;
4116         r_texture_normalizationcube = NULL;
4117         r_texture_fogattenuation = NULL;
4118         r_texture_fogheighttexture = NULL;
4119         r_texture_gammaramps = NULL;
4120         r_texture_numcubemaps = 0;
4121         //r_texture_fogintensity = NULL;
4122         memset(&r_fb, 0, sizeof(r_fb));
4123         R_GLSL_Restart_f();
4124
4125         r_glsl_permutation = NULL;
4126         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4127         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4128         glslshaderstring = NULL;
4129 #ifdef SUPPORTD3D
4130         r_hlsl_permutation = NULL;
4131         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4132         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4133 #endif
4134         hlslshaderstring = NULL;
4135 }
4136
4137 static void gl_main_newmap(void)
4138 {
4139         // FIXME: move this code to client
4140         char *entities, entname[MAX_QPATH];
4141         if (r_qwskincache)
4142                 Mem_Free(r_qwskincache);
4143         r_qwskincache = NULL;
4144         r_qwskincache_size = 0;
4145         if (cl.worldmodel)
4146         {
4147                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4148                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4149                 {
4150                         CL_ParseEntityLump(entities);
4151                         Mem_Free(entities);
4152                         return;
4153                 }
4154                 if (cl.worldmodel->brush.entities)
4155                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4156         }
4157         R_Main_FreeViewCache();
4158
4159         R_FrameData_Reset();
4160 }
4161
4162 void GL_Main_Init(void)
4163 {
4164         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4165
4166         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4167         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4168         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4169         if (gamemode == GAME_NEHAHRA)
4170         {
4171                 Cvar_RegisterVariable (&gl_fogenable);
4172                 Cvar_RegisterVariable (&gl_fogdensity);
4173                 Cvar_RegisterVariable (&gl_fogred);
4174                 Cvar_RegisterVariable (&gl_foggreen);
4175                 Cvar_RegisterVariable (&gl_fogblue);
4176                 Cvar_RegisterVariable (&gl_fogstart);
4177                 Cvar_RegisterVariable (&gl_fogend);
4178                 Cvar_RegisterVariable (&gl_skyclip);
4179         }
4180         Cvar_RegisterVariable(&r_motionblur);
4181         Cvar_RegisterVariable(&r_damageblur);
4182         Cvar_RegisterVariable(&r_motionblur_averaging);
4183         Cvar_RegisterVariable(&r_motionblur_randomize);
4184         Cvar_RegisterVariable(&r_motionblur_minblur);
4185         Cvar_RegisterVariable(&r_motionblur_maxblur);
4186         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4187         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4188         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4189         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4190         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4191         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4192         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4193         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4194         Cvar_RegisterVariable(&r_equalize_entities_by);
4195         Cvar_RegisterVariable(&r_equalize_entities_to);
4196         Cvar_RegisterVariable(&r_depthfirst);
4197         Cvar_RegisterVariable(&r_useinfinitefarclip);
4198         Cvar_RegisterVariable(&r_farclip_base);
4199         Cvar_RegisterVariable(&r_farclip_world);
4200         Cvar_RegisterVariable(&r_nearclip);
4201         Cvar_RegisterVariable(&r_deformvertexes);
4202         Cvar_RegisterVariable(&r_transparent);
4203         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4204         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4205         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4206         Cvar_RegisterVariable(&r_showoverdraw);
4207         Cvar_RegisterVariable(&r_showbboxes);
4208         Cvar_RegisterVariable(&r_showsurfaces);
4209         Cvar_RegisterVariable(&r_showtris);
4210         Cvar_RegisterVariable(&r_shownormals);
4211         Cvar_RegisterVariable(&r_showlighting);
4212         Cvar_RegisterVariable(&r_showshadowvolumes);
4213         Cvar_RegisterVariable(&r_showcollisionbrushes);
4214         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4215         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4216         Cvar_RegisterVariable(&r_showdisabledepthtest);
4217         Cvar_RegisterVariable(&r_drawportals);
4218         Cvar_RegisterVariable(&r_drawentities);
4219         Cvar_RegisterVariable(&r_draw2d);
4220         Cvar_RegisterVariable(&r_drawworld);
4221         Cvar_RegisterVariable(&r_cullentities_trace);
4222         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4223         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4224         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4225         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4226         Cvar_RegisterVariable(&r_sortentities);
4227         Cvar_RegisterVariable(&r_drawviewmodel);
4228         Cvar_RegisterVariable(&r_drawexteriormodel);
4229         Cvar_RegisterVariable(&r_speeds);
4230         Cvar_RegisterVariable(&r_fullbrights);
4231         Cvar_RegisterVariable(&r_wateralpha);
4232         Cvar_RegisterVariable(&r_dynamic);
4233         Cvar_RegisterVariable(&r_fakelight);
4234         Cvar_RegisterVariable(&r_fakelight_intensity);
4235         Cvar_RegisterVariable(&r_fullbright);
4236         Cvar_RegisterVariable(&r_shadows);
4237         Cvar_RegisterVariable(&r_shadows_darken);
4238         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4239         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4240         Cvar_RegisterVariable(&r_shadows_throwdistance);
4241         Cvar_RegisterVariable(&r_shadows_throwdirection);
4242         Cvar_RegisterVariable(&r_shadows_focus);
4243         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4244         Cvar_RegisterVariable(&r_shadows_shadowmapbias);
4245         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4246         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4247         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4248         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4249         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4250         Cvar_RegisterVariable(&r_fog_exp2);
4251         Cvar_RegisterVariable(&r_fog_clear);
4252         Cvar_RegisterVariable(&r_drawfog);
4253         Cvar_RegisterVariable(&r_transparentdepthmasking);
4254         Cvar_RegisterVariable(&r_transparent_sortmindist);
4255         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4256         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4257         Cvar_RegisterVariable(&r_texture_dds_load);
4258         Cvar_RegisterVariable(&r_texture_dds_save);
4259         Cvar_RegisterVariable(&r_textureunits);
4260         Cvar_RegisterVariable(&gl_combine);
4261         Cvar_RegisterVariable(&r_usedepthtextures);
4262         Cvar_RegisterVariable(&r_viewfbo);
4263         Cvar_RegisterVariable(&r_viewscale);
4264         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4265         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4266         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4267         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4268         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4269         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4270         Cvar_RegisterVariable(&r_glsl);
4271         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4272         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4273         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4274         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4275         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4276         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4277         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4278         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4279         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4280         Cvar_RegisterVariable(&r_glsl_postprocess);
4281         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4282         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4283         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4284         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4285         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4286         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4287         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4288         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4289         Cvar_RegisterVariable(&r_celshading);
4290         Cvar_RegisterVariable(&r_celoutlines);
4291
4292         Cvar_RegisterVariable(&r_water);
4293         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4294         Cvar_RegisterVariable(&r_water_clippingplanebias);
4295         Cvar_RegisterVariable(&r_water_refractdistort);
4296         Cvar_RegisterVariable(&r_water_reflectdistort);
4297         Cvar_RegisterVariable(&r_water_scissormode);
4298         Cvar_RegisterVariable(&r_water_lowquality);
4299         Cvar_RegisterVariable(&r_water_hideplayer);
4300         Cvar_RegisterVariable(&r_water_fbo);
4301
4302         Cvar_RegisterVariable(&r_lerpsprites);
4303         Cvar_RegisterVariable(&r_lerpmodels);
4304         Cvar_RegisterVariable(&r_lerplightstyles);
4305         Cvar_RegisterVariable(&r_waterscroll);
4306         Cvar_RegisterVariable(&r_bloom);
4307         Cvar_RegisterVariable(&r_bloom_colorscale);
4308         Cvar_RegisterVariable(&r_bloom_brighten);
4309         Cvar_RegisterVariable(&r_bloom_blur);
4310         Cvar_RegisterVariable(&r_bloom_resolution);
4311         Cvar_RegisterVariable(&r_bloom_colorexponent);
4312         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4313         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4314         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4315         Cvar_RegisterVariable(&r_hdr_glowintensity);
4316         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4317         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4318         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4319         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4320         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4321         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4322         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4323         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4324         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4325         Cvar_RegisterVariable(&developer_texturelogging);
4326         Cvar_RegisterVariable(&gl_lightmaps);
4327         Cvar_RegisterVariable(&r_test);
4328         Cvar_RegisterVariable(&r_batch_multidraw);
4329         Cvar_RegisterVariable(&r_batch_multidraw_mintriangles);
4330         Cvar_RegisterVariable(&r_glsl_skeletal);
4331         Cvar_RegisterVariable(&r_glsl_saturation);
4332         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4333         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4334         Cvar_RegisterVariable(&r_framedatasize);
4335         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4336                 Cvar_SetValue("r_fullbrights", 0);
4337         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4338 }
4339
4340 void Render_Init(void)
4341 {
4342         gl_backend_init();
4343         R_Textures_Init();
4344         GL_Main_Init();
4345         Font_Init();
4346         GL_Draw_Init();
4347         R_Shadow_Init();
4348         R_Sky_Init();
4349         GL_Surf_Init();
4350         Sbar_Init();
4351         R_Particles_Init();
4352         R_Explosion_Init();
4353         R_LightningBeams_Init();
4354         Mod_RenderInit();
4355 }
4356
4357 /*
4358 ===============
4359 GL_Init
4360 ===============
4361 */
4362 #ifndef USE_GLES2
4363 extern char *ENGINE_EXTENSIONS;
4364 void GL_Init (void)
4365 {
4366         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4367         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4368         gl_version = (const char *)qglGetString(GL_VERSION);
4369         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4370
4371         if (!gl_extensions)
4372                 gl_extensions = "";
4373         if (!gl_platformextensions)
4374                 gl_platformextensions = "";
4375
4376         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4377         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4378         Con_Printf("GL_VERSION: %s\n", gl_version);
4379         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4380         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4381
4382         VID_CheckExtensions();
4383
4384         // LordHavoc: report supported extensions
4385         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4386
4387         // clear to black (loading plaque will be seen over this)
4388         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4389 }
4390 #endif
4391
4392 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4393 {
4394         int i;
4395         mplane_t *p;
4396         if (r_trippy.integer)
4397                 return false;
4398         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4399         {
4400                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4401                 if (i == 4)
4402                         continue;
4403                 p = r_refdef.view.frustum + i;
4404                 switch(p->signbits)
4405                 {
4406                 default:
4407                 case 0:
4408                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4409                                 return true;
4410                         break;
4411                 case 1:
4412                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4413                                 return true;
4414                         break;
4415                 case 2:
4416                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4417                                 return true;
4418                         break;
4419                 case 3:
4420                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4421                                 return true;
4422                         break;
4423                 case 4:
4424                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4425                                 return true;
4426                         break;
4427                 case 5:
4428                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4429                                 return true;
4430                         break;
4431                 case 6:
4432                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4433                                 return true;
4434                         break;
4435                 case 7:
4436                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4437                                 return true;
4438                         break;
4439                 }
4440         }
4441         return false;
4442 }
4443
4444 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4445 {
4446         int i;
4447         const mplane_t *p;
4448         if (r_trippy.integer)
4449                 return false;
4450         for (i = 0;i < numplanes;i++)
4451         {
4452                 p = planes + i;
4453                 switch(p->signbits)
4454                 {
4455                 default:
4456                 case 0:
4457                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4458                                 return true;
4459                         break;
4460                 case 1:
4461                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4462                                 return true;
4463                         break;
4464                 case 2:
4465                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4466                                 return true;
4467                         break;
4468                 case 3:
4469                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4470                                 return true;
4471                         break;
4472                 case 4:
4473                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4474                                 return true;
4475                         break;
4476                 case 5:
4477                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4478                                 return true;
4479                         break;
4480                 case 6:
4481                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4482                                 return true;
4483                         break;
4484                 case 7:
4485                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4486                                 return true;
4487                         break;
4488                 }
4489         }
4490         return false;
4491 }
4492
4493 //==================================================================================
4494
4495 // LordHavoc: this stores temporary data used within the same frame
4496
4497 typedef struct r_framedata_mem_s
4498 {
4499         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4500         size_t size; // how much usable space
4501         size_t current; // how much space in use
4502         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4503         size_t wantedsize; // how much space was allocated
4504         unsigned char *data; // start of real data (16byte aligned)
4505 }
4506 r_framedata_mem_t;
4507
4508 static r_framedata_mem_t *r_framedata_mem;
4509
4510 void R_FrameData_Reset(void)
4511 {
4512         while (r_framedata_mem)
4513         {
4514                 r_framedata_mem_t *next = r_framedata_mem->purge;
4515                 Mem_Free(r_framedata_mem);
4516                 r_framedata_mem = next;
4517         }
4518 }
4519
4520 static void R_FrameData_Resize(void)
4521 {
4522         size_t wantedsize;
4523         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4524         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4525         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4526         {
4527                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4528                 newmem->wantedsize = wantedsize;
4529                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4530                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4531                 newmem->current = 0;
4532                 newmem->mark = 0;
4533                 newmem->purge = r_framedata_mem;
4534                 r_framedata_mem = newmem;
4535         }
4536 }
4537
4538 void R_FrameData_NewFrame(void)
4539 {
4540         R_FrameData_Resize();
4541         if (!r_framedata_mem)
4542                 return;
4543         // if we ran out of space on the last frame, free the old memory now
4544         while (r_framedata_mem->purge)
4545         {
4546                 // repeatedly remove the second item in the list, leaving only head
4547                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4548                 Mem_Free(r_framedata_mem->purge);
4549                 r_framedata_mem->purge = next;
4550         }
4551         // reset the current mem pointer
4552         r_framedata_mem->current = 0;
4553         r_framedata_mem->mark = 0;
4554 }
4555
4556 void *R_FrameData_Alloc(size_t size)
4557 {
4558         void *data;
4559
4560         // align to 16 byte boundary - the data pointer is already aligned, so we
4561         // only need to ensure the size of every allocation is also aligned
4562         size = (size + 15) & ~15;
4563
4564         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4565         {
4566                 // emergency - we ran out of space, allocate more memory
4567                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4568                 R_FrameData_Resize();
4569         }
4570
4571         data = r_framedata_mem->data + r_framedata_mem->current;
4572         r_framedata_mem->current += size;
4573
4574         // count the usage for stats
4575         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4576         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4577
4578         return (void *)data;
4579 }
4580
4581 void *R_FrameData_Store(size_t size, void *data)
4582 {
4583         void *d = R_FrameData_Alloc(size);
4584         if (d && data)
4585                 memcpy(d, data, size);
4586         return d;
4587 }
4588
4589 void R_FrameData_SetMark(void)
4590 {
4591         if (!r_framedata_mem)
4592                 return;
4593         r_framedata_mem->mark = r_framedata_mem->current;
4594 }
4595
4596 void R_FrameData_ReturnToMark(void)
4597 {
4598         if (!r_framedata_mem)
4599                 return;
4600         r_framedata_mem->current = r_framedata_mem->mark;
4601 }
4602
4603 //==================================================================================
4604
4605 // LordHavoc: animcache originally written by Echon, rewritten since then
4606
4607 /**
4608  * Animation cache prevents re-generating mesh data for an animated model
4609  * multiple times in one frame for lighting, shadowing, reflections, etc.
4610  */
4611
4612 void R_AnimCache_Free(void)
4613 {
4614 }
4615
4616 void R_AnimCache_ClearCache(void)
4617 {
4618         int i;
4619         entity_render_t *ent;
4620
4621         for (i = 0;i < r_refdef.scene.numentities;i++)
4622         {
4623                 ent = r_refdef.scene.entities[i];
4624                 ent->animcache_vertex3f = NULL;
4625                 ent->animcache_normal3f = NULL;
4626                 ent->animcache_svector3f = NULL;
4627                 ent->animcache_tvector3f = NULL;
4628                 ent->animcache_vertexmesh = NULL;
4629                 ent->animcache_vertex3fbuffer = NULL;
4630                 ent->animcache_vertexmeshbuffer = NULL;
4631                 ent->animcache_skeletaltransform3x4 = NULL;
4632         }
4633 }
4634
4635 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4636 {
4637         int i;
4638
4639         // check if we need the meshbuffers
4640         if (!vid.useinterleavedarrays)
4641                 return;
4642
4643         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4644                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4645         // TODO: upload vertex3f buffer?
4646         if (ent->animcache_vertexmesh)
4647         {
4648                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4649                 for (i = 0;i < numvertices;i++)
4650                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4651                 if (ent->animcache_svector3f)
4652                         for (i = 0;i < numvertices;i++)
4653                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4654                 if (ent->animcache_tvector3f)
4655                         for (i = 0;i < numvertices;i++)
4656                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4657                 if (ent->animcache_normal3f)
4658                         for (i = 0;i < numvertices;i++)
4659                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4660                 // TODO: upload vertexmeshbuffer?
4661         }
4662 }
4663
4664 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4665 {
4666         dp_model_t *model = ent->model;
4667         int numvertices;
4668
4669         // cache skeletal animation data first (primarily for gpu-skinning)
4670         if (!ent->animcache_skeletaltransform3x4 && model->num_bones > 0)
4671         {
4672                 int i;
4673                 int blends;
4674                 const skeleton_t *skeleton = ent->skeleton;
4675                 const frameblend_t *frameblend = ent->frameblend;
4676                 float *boneposerelative;
4677                 float m[12];
4678                 static float bonepose[256][12];
4679                 ent->animcache_skeletaltransform3x4 = R_FrameData_Alloc(sizeof(float[3][4]) * model->num_bones);
4680                 boneposerelative = ent->animcache_skeletaltransform3x4;
4681                 if (skeleton && !skeleton->relativetransforms)
4682                         skeleton = NULL;
4683                 // resolve hierarchy and make relative transforms (deforms) which the shader wants
4684                 if (skeleton)
4685                 {
4686                         for (i = 0;i < model->num_bones;i++)
4687                         {
4688                                 Matrix4x4_ToArray12FloatD3D(&skeleton->relativetransforms[i], m);
4689                                 if (model->data_bones[i].parent >= 0)
4690                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4691                                 else
4692                                         memcpy(bonepose[i], m, sizeof(m));
4693
4694                                 // create a relative deformation matrix to describe displacement
4695                                 // from the base mesh, which is used by the actual weighting
4696                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4697                         }
4698                 }
4699                 else
4700                 {
4701                         for (i = 0;i < model->num_bones;i++)
4702                         {
4703                                 const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[0].subframe * model->num_bones + i);
4704                                 float lerp = frameblend[0].lerp,
4705                                         tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4706                                         rx = pose7s[3] * lerp,
4707                                         ry = pose7s[4] * lerp,
4708                                         rz = pose7s[5] * lerp,
4709                                         rw = pose7s[6] * lerp,
4710                                         dx = tx*rw + ty*rz - tz*ry,
4711                                         dy = -tx*rz + ty*rw + tz*rx,
4712                                         dz = tx*ry - ty*rx + tz*rw,
4713                                         dw = -tx*rx - ty*ry - tz*rz,
4714                                         scale, sx, sy, sz, sw;
4715                                 for (blends = 1;blends < MAX_FRAMEBLENDS && frameblend[blends].lerp > 0;blends++)
4716                                 {
4717                                         const short * RESTRICT pose7s = model->data_poses7s + 7 * (frameblend[blends].subframe * model->num_bones + i);
4718                                         float lerp = frameblend[blends].lerp,
4719                                                 tx = pose7s[0], ty = pose7s[1], tz = pose7s[2],
4720                                                 qx = pose7s[3], qy = pose7s[4], qz = pose7s[5], qw = pose7s[6];
4721                                         if(rx*qx + ry*qy + rz*qz + rw*qw < 0) lerp = -lerp;
4722                                         qx *= lerp;
4723                                         qy *= lerp;
4724                                         qz *= lerp;
4725                                         qw *= lerp;
4726                                         rx += qx;
4727                                         ry += qy;
4728                                         rz += qz;
4729                                         rw += qw;
4730                                         dx += tx*qw + ty*qz - tz*qy;
4731                                         dy += -tx*qz + ty*qw + tz*qx;
4732                                         dz += tx*qy - ty*qx + tz*qw;
4733                                         dw += -tx*qx - ty*qy - tz*qz;
4734                                 }
4735                                 scale = 1.0f / (rx*rx + ry*ry + rz*rz + rw*rw);
4736                                 sx = rx * scale;
4737                                 sy = ry * scale;
4738                                 sz = rz * scale;
4739                                 sw = rw * scale;
4740                                 m[0] = sw*rw + sx*rx - sy*ry - sz*rz;
4741                                 m[1] = 2*(sx*ry - sw*rz);
4742                                 m[2] = 2*(sx*rz + sw*ry);
4743                                 m[3] = model->num_posescale*(dx*sw - dy*sz + dz*sy - dw*sx);
4744                                 m[4] = 2*(sx*ry + sw*rz);
4745                                 m[5] = sw*rw + sy*ry - sx*rx - sz*rz;
4746                                 m[6] = 2*(sy*rz - sw*rx);
4747                                 m[7] = model->num_posescale*(dx*sz + dy*sw - dz*sx - dw*sy);
4748                                 m[8] = 2*(sx*rz - sw*ry);
4749                                 m[9] = 2*(sy*rz + sw*rx);
4750                                 m[10] = sw*rw + sz*rz - sx*rx - sy*ry;
4751                                 m[11] = model->num_posescale*(dy*sx + dz*sw - dx*sy - dw*sz);
4752                                 if (i == r_skeletal_debugbone.integer)
4753                                         m[r_skeletal_debugbonecomponent.integer % 12] += r_skeletal_debugbonevalue.value;
4754                                 m[3] *= r_skeletal_debugtranslatex.value;
4755                                 m[7] *= r_skeletal_debugtranslatey.value;
4756                                 m[11] *= r_skeletal_debugtranslatez.value;
4757                                 if (model->data_bones[i].parent >= 0)
4758                                         R_ConcatTransforms(bonepose[model->data_bones[i].parent], m, bonepose[i]);
4759                                 else
4760                                         memcpy(bonepose[i], m, sizeof(m));
4761                                 // create a relative deformation matrix to describe displacement
4762                                 // from the base mesh, which is used by the actual weighting
4763                                 R_ConcatTransforms(bonepose[i], model->data_baseboneposeinverse + i * 12, boneposerelative + i * 12);
4764                         }
4765                 }
4766         }
4767
4768         // see if it's already cached this frame
4769         if (ent->animcache_vertex3f)
4770         {
4771                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4772                 if (wantnormals || wanttangents)
4773                 {
4774                         if (ent->animcache_normal3f)
4775                                 wantnormals = false;
4776                         if (ent->animcache_svector3f)
4777                                 wanttangents = false;
4778                         if (wantnormals || wanttangents)
4779                         {
4780                                 numvertices = model->surfmesh.num_vertices;
4781                                 if (wantnormals)
4782                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4783                                 if (wanttangents)
4784                                 {
4785                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4786                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4787                                 }
4788                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4789                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4790                         }
4791                 }
4792         }
4793         else
4794         {
4795                 // see if this ent is worth caching
4796                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4797                         return false;
4798                 // skip entity if the shader backend has a cheaper way
4799                 if (model->surfmesh.data_skeletalindex4ub && r_glsl_skeletal.integer)
4800                 {
4801                         switch (vid.renderpath)
4802                         {
4803                         case RENDERPATH_GL20:
4804                                 return false;
4805                         case RENDERPATH_GL11:
4806                         case RENDERPATH_GL13:
4807                         case RENDERPATH_GLES1:
4808                         case RENDERPATH_GLES2:
4809                         case RENDERPATH_D3D9:
4810                         case RENDERPATH_D3D10:
4811                         case RENDERPATH_D3D11:
4812                         case RENDERPATH_SOFT:
4813                                 break;
4814                         }
4815                 }
4816                 // get some memory for this entity and generate mesh data
4817                 numvertices = model->surfmesh.num_vertices;
4818                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4819                 if (wantnormals)
4820                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4821                 if (wanttangents)
4822                 {
4823                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4824                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4825                 }
4826                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4827                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4828         }
4829         return true;
4830 }
4831
4832 void R_AnimCache_CacheVisibleEntities(void)
4833 {
4834         int i;
4835         qboolean wantnormals = true;
4836         qboolean wanttangents = !r_showsurfaces.integer;
4837
4838         switch(vid.renderpath)
4839         {
4840         case RENDERPATH_GL20:
4841         case RENDERPATH_D3D9:
4842         case RENDERPATH_D3D10:
4843         case RENDERPATH_D3D11:
4844         case RENDERPATH_GLES2:
4845                 break;
4846         case RENDERPATH_GL11:
4847         case RENDERPATH_GL13:
4848         case RENDERPATH_GLES1:
4849                 wanttangents = false;
4850                 break;
4851         case RENDERPATH_SOFT:
4852                 break;
4853         }
4854
4855         if (r_shownormals.integer)
4856                 wanttangents = wantnormals = true;
4857
4858         // TODO: thread this
4859         // NOTE: R_PrepareRTLights() also caches entities
4860
4861         for (i = 0;i < r_refdef.scene.numentities;i++)
4862                 if (r_refdef.viewcache.entityvisible[i])
4863                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4864 }
4865
4866 //==================================================================================
4867
4868 extern cvar_t r_overheadsprites_pushback;
4869
4870 static void R_View_UpdateEntityLighting (void)
4871 {
4872         int i;
4873         entity_render_t *ent;
4874         vec3_t tempdiffusenormal, avg;
4875         vec_t f, fa, fd, fdd;
4876         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4877
4878         for (i = 0;i < r_refdef.scene.numentities;i++)
4879         {
4880                 ent = r_refdef.scene.entities[i];
4881
4882                 // skip unseen models
4883                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4884                         continue;
4885
4886                 // skip bsp models
4887                 if (ent->model && ent->model == cl.worldmodel)
4888                 {
4889                         // TODO: use modellight for r_ambient settings on world?
4890                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4891                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4892                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4893                         continue;
4894                 }
4895                 
4896                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4897                 {
4898                         // aleady updated by CSQC
4899                         // TODO: force modellight on BSP models in this case?
4900                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
4901                 }
4902                 else
4903                 {
4904                         // fetch the lighting from the worldmodel data
4905                         VectorClear(ent->modellight_ambient);
4906                         VectorClear(ent->modellight_diffuse);
4907                         VectorClear(tempdiffusenormal);
4908                         if (ent->flags & RENDER_LIGHT)
4909                         {
4910                                 vec3_t org;
4911                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4912
4913                                 // complete lightning for lit sprites
4914                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4915                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4916                                 {
4917                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4918                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
4919                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4920                                 }
4921                                 else
4922                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4923
4924                                 if(ent->flags & RENDER_EQUALIZE)
4925                                 {
4926                                         // first fix up ambient lighting...
4927                                         if(r_equalize_entities_minambient.value > 0)
4928                                         {
4929                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4930                                                 if(fd > 0)
4931                                                 {
4932                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4933                                                         if(fa < r_equalize_entities_minambient.value * fd)
4934                                                         {
4935                                                                 // solve:
4936                                                                 //   fa'/fd' = minambient
4937                                                                 //   fa'+0.25*fd' = fa+0.25*fd
4938                                                                 //   ...
4939                                                                 //   fa' = fd' * minambient
4940                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
4941                                                                 //   ...
4942                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4943                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4944                                                                 //   ...
4945                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4946                                                                 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
4947                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4948                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4949                                                         }
4950                                                 }
4951                                         }
4952
4953                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4954                                         {
4955                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4956                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4957                                                 f = fa + 0.25 * fd;
4958                                                 if(f > 0)
4959                                                 {
4960                                                         // adjust brightness and saturation to target
4961                                                         avg[0] = avg[1] = avg[2] = fa / f;
4962                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4963                                                         avg[0] = avg[1] = avg[2] = fd / f;
4964                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4965                                                 }
4966                                         }
4967                                 }
4968                         }
4969                         else // highly rare
4970                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
4971                 }
4972
4973                 // move the light direction into modelspace coordinates for lighting code
4974                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4975                 if(VectorLength2(ent->modellight_lightdir) == 0)
4976                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4977                 VectorNormalize(ent->modellight_lightdir);
4978         }
4979 }
4980
4981 #define MAX_LINEOFSIGHTTRACES 64
4982
4983 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4984 {
4985         int i;
4986         vec3_t boxmins, boxmaxs;
4987         vec3_t start;
4988         vec3_t end;
4989         dp_model_t *model = r_refdef.scene.worldmodel;
4990
4991         if (!model || !model->brush.TraceLineOfSight)
4992                 return true;
4993
4994         // expand the box a little
4995         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4996         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4997         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4998         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4999         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
5000         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
5001
5002         // return true if eye is inside enlarged box
5003         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
5004                 return true;
5005
5006         // try center
5007         VectorCopy(eye, start);
5008         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
5009         if (model->brush.TraceLineOfSight(model, start, end))
5010                 return true;
5011
5012         // try various random positions
5013         for (i = 0;i < numsamples;i++)
5014         {
5015                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
5016                 if (model->brush.TraceLineOfSight(model, start, end))
5017                         return true;
5018         }
5019
5020         return false;
5021 }
5022
5023
5024 static void R_View_UpdateEntityVisible (void)
5025 {
5026         int i;
5027         int renderimask;
5028         int samples;
5029         entity_render_t *ent;
5030
5031         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5032                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
5033                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
5034                 :                                                          RENDER_EXTERIORMODEL;
5035         if (!r_drawviewmodel.integer)
5036                 renderimask |= RENDER_VIEWMODEL;
5037         if (!r_drawexteriormodel.integer)
5038                 renderimask |= RENDER_EXTERIORMODEL;
5039         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
5040         {
5041                 // worldmodel can check visibility
5042                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
5043                 for (i = 0;i < r_refdef.scene.numentities;i++)
5044                 {
5045                         ent = r_refdef.scene.entities[i];
5046                         if (!(ent->flags & renderimask))
5047                         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)))
5048                         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))
5049                                 r_refdef.viewcache.entityvisible[i] = true;
5050                 }
5051         }
5052         else
5053         {
5054                 // no worldmodel or it can't check visibility
5055                 for (i = 0;i < r_refdef.scene.numentities;i++)
5056                 {
5057                         ent = r_refdef.scene.entities[i];
5058                         r_refdef.viewcache.entityvisible[i] = !(ent->flags & renderimask) && ((ent->model && ent->model->type == mod_sprite && (ent->model->sprite.sprnum_type == SPR_LABEL || ent->model->sprite.sprnum_type == SPR_LABEL_SCALE)) || !R_CullBox(ent->mins, ent->maxs));
5059                 }
5060         }
5061         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
5062                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
5063         {
5064                 for (i = 0;i < r_refdef.scene.numentities;i++)
5065                 {
5066                         if (!r_refdef.viewcache.entityvisible[i])
5067                                 continue;
5068                         ent = r_refdef.scene.entities[i];
5069                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
5070                         {
5071                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
5072                                 if (samples < 0)
5073                                         continue; // temp entities do pvs only
5074                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
5075                                         ent->last_trace_visibility = realtime;
5076                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
5077                                         r_refdef.viewcache.entityvisible[i] = 0;
5078                         }
5079                 }
5080         }
5081 }
5082
5083 /// only used if skyrendermasked, and normally returns false
5084 static int R_DrawBrushModelsSky (void)
5085 {
5086         int i, sky;
5087         entity_render_t *ent;
5088
5089         sky = false;
5090         for (i = 0;i < r_refdef.scene.numentities;i++)
5091         {
5092                 if (!r_refdef.viewcache.entityvisible[i])
5093                         continue;
5094                 ent = r_refdef.scene.entities[i];
5095                 if (!ent->model || !ent->model->DrawSky)
5096                         continue;
5097                 ent->model->DrawSky(ent);
5098                 sky = true;
5099         }
5100         return sky;
5101 }
5102
5103 static void R_DrawNoModel(entity_render_t *ent);
5104 static void R_DrawModels(void)
5105 {
5106         int i;
5107         entity_render_t *ent;
5108
5109         for (i = 0;i < r_refdef.scene.numentities;i++)
5110         {
5111                 if (!r_refdef.viewcache.entityvisible[i])
5112                         continue;
5113                 ent = r_refdef.scene.entities[i];
5114                 r_refdef.stats.entities++;
5115                 /*
5116                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
5117                 {
5118                         vec3_t f, l, u, o;
5119                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
5120                         Con_Printf("R_DrawModels\n");
5121                         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]);
5122                         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);
5123                         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);
5124                 }
5125                 */
5126                 if (ent->model && ent->model->Draw != NULL)
5127                         ent->model->Draw(ent);
5128                 else
5129                         R_DrawNoModel(ent);
5130         }
5131 }
5132
5133 static void R_DrawModelsDepth(void)
5134 {
5135         int i;
5136         entity_render_t *ent;
5137
5138         for (i = 0;i < r_refdef.scene.numentities;i++)
5139         {
5140                 if (!r_refdef.viewcache.entityvisible[i])
5141                         continue;
5142                 ent = r_refdef.scene.entities[i];
5143                 if (ent->model && ent->model->DrawDepth != NULL)
5144                         ent->model->DrawDepth(ent);
5145         }
5146 }
5147
5148 static void R_DrawModelsDebug(void)
5149 {
5150         int i;
5151         entity_render_t *ent;
5152
5153         for (i = 0;i < r_refdef.scene.numentities;i++)
5154         {
5155                 if (!r_refdef.viewcache.entityvisible[i])
5156                         continue;
5157                 ent = r_refdef.scene.entities[i];
5158                 if (ent->model && ent->model->DrawDebug != NULL)
5159                         ent->model->DrawDebug(ent);
5160         }
5161 }
5162
5163 static void R_DrawModelsAddWaterPlanes(void)
5164 {
5165         int i;
5166         entity_render_t *ent;
5167
5168         for (i = 0;i < r_refdef.scene.numentities;i++)
5169         {
5170                 if (!r_refdef.viewcache.entityvisible[i])
5171                         continue;
5172                 ent = r_refdef.scene.entities[i];
5173                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5174                         ent->model->DrawAddWaterPlanes(ent);
5175         }
5176 }
5177
5178 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}};
5179
5180 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5181 {
5182         if (r_hdr_irisadaptation.integer)
5183         {
5184                 vec3_t p;
5185                 vec3_t ambient;
5186                 vec3_t diffuse;
5187                 vec3_t diffusenormal;
5188                 vec3_t forward;
5189                 vec_t brightness = 0.0f;
5190                 vec_t goal;
5191                 vec_t current;
5192                 vec_t d;
5193                 int c;
5194                 VectorCopy(r_refdef.view.forward, forward);
5195                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5196                 {
5197                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5198                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5199                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5200                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5201                         d = DotProduct(forward, diffusenormal);
5202                         brightness += VectorLength(ambient);
5203                         if (d > 0)
5204                                 brightness += d * VectorLength(diffuse);
5205                 }
5206                 brightness *= 1.0f / c;
5207                 brightness += 0.00001f; // make sure it's never zero
5208                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5209                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5210                 current = r_hdr_irisadaptation_value.value;
5211                 if (current < goal)
5212                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5213                 else if (current > goal)
5214                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5215                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5216                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5217         }
5218         else if (r_hdr_irisadaptation_value.value != 1.0f)
5219                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5220 }
5221
5222 static void R_View_SetFrustum(const int *scissor)
5223 {
5224         int i;
5225         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5226         vec3_t forward, left, up, origin, v;
5227
5228         if(scissor)
5229         {
5230                 // flipped x coordinates (because x points left here)
5231                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5232                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5233
5234                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5235                 switch(vid.renderpath)
5236                 {
5237                         case RENDERPATH_D3D9:
5238                         case RENDERPATH_D3D10:
5239                         case RENDERPATH_D3D11:
5240                                 // non-flipped y coordinates
5241                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5242                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5243                                 break;
5244                         case RENDERPATH_SOFT:
5245                         case RENDERPATH_GL11:
5246                         case RENDERPATH_GL13:
5247                         case RENDERPATH_GL20:
5248                         case RENDERPATH_GLES1:
5249                         case RENDERPATH_GLES2:
5250                                 // non-flipped y coordinates
5251                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5252                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5253                                 break;
5254                 }
5255         }
5256
5257         // we can't trust r_refdef.view.forward and friends in reflected scenes
5258         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5259
5260 #if 0
5261         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5262         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5263         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5264         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5265         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5266         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5267         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5268         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5269         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5270         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5271         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5272         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5273 #endif
5274
5275 #if 0
5276         zNear = r_refdef.nearclip;
5277         nudge = 1.0 - 1.0 / (1<<23);
5278         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5279         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5280         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5281         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5282         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5283         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5284         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5285         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5286 #endif
5287
5288
5289
5290 #if 0
5291         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5292         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5293         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5294         r_refdef.view.frustum[0].dist = m[15] - m[12];
5295
5296         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5297         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5298         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5299         r_refdef.view.frustum[1].dist = m[15] + m[12];
5300
5301         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5302         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5303         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5304         r_refdef.view.frustum[2].dist = m[15] - m[13];
5305
5306         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5307         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5308         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5309         r_refdef.view.frustum[3].dist = m[15] + m[13];
5310
5311         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5312         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5313         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5314         r_refdef.view.frustum[4].dist = m[15] - m[14];
5315
5316         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5317         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5318         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5319         r_refdef.view.frustum[5].dist = m[15] + m[14];
5320 #endif
5321
5322         if (r_refdef.view.useperspective)
5323         {
5324                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5325                 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]);
5326                 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]);
5327                 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]);
5328                 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]);
5329
5330                 // then the normals from the corners relative to origin
5331                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5332                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5333                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5334                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5335
5336                 // in a NORMAL view, forward cross left == up
5337                 // in a REFLECTED view, forward cross left == down
5338                 // so our cross products above need to be adjusted for a left handed coordinate system
5339                 CrossProduct(forward, left, v);
5340                 if(DotProduct(v, up) < 0)
5341                 {
5342                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5343                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5344                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5345                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5346                 }
5347
5348                 // Leaving those out was a mistake, those were in the old code, and they
5349                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5350                 // I couldn't reproduce it after adding those normalizations. --blub
5351                 VectorNormalize(r_refdef.view.frustum[0].normal);
5352                 VectorNormalize(r_refdef.view.frustum[1].normal);
5353                 VectorNormalize(r_refdef.view.frustum[2].normal);
5354                 VectorNormalize(r_refdef.view.frustum[3].normal);
5355
5356                 // make the corners absolute
5357                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5358                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5359                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5360                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5361
5362                 // one more normal
5363                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5364
5365                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5366                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5367                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5368                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5369                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5370         }
5371         else
5372         {
5373                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5374                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5375                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5376                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5377                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5378                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5379                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5380                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5381                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5382                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5383         }
5384         r_refdef.view.numfrustumplanes = 5;
5385
5386         if (r_refdef.view.useclipplane)
5387         {
5388                 r_refdef.view.numfrustumplanes = 6;
5389                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5390         }
5391
5392         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5393                 PlaneClassify(r_refdef.view.frustum + i);
5394
5395         // LordHavoc: note to all quake engine coders, Quake had a special case
5396         // for 90 degrees which assumed a square view (wrong), so I removed it,
5397         // Quake2 has it disabled as well.
5398
5399         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5400         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5401         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5402         //PlaneClassify(&frustum[0]);
5403
5404         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5405         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5406         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5407         //PlaneClassify(&frustum[1]);
5408
5409         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5410         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5411         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5412         //PlaneClassify(&frustum[2]);
5413
5414         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5415         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5416         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5417         //PlaneClassify(&frustum[3]);
5418
5419         // nearclip plane
5420         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5421         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5422         //PlaneClassify(&frustum[4]);
5423 }
5424
5425 static void R_View_UpdateWithScissor(const int *myscissor)
5426 {
5427         R_Main_ResizeViewCache();
5428         R_View_SetFrustum(myscissor);
5429         R_View_WorldVisibility(r_refdef.view.useclipplane);
5430         R_View_UpdateEntityVisible();
5431         R_View_UpdateEntityLighting();
5432 }
5433
5434 static void R_View_Update(void)
5435 {
5436         R_Main_ResizeViewCache();
5437         R_View_SetFrustum(NULL);
5438         R_View_WorldVisibility(r_refdef.view.useclipplane);
5439         R_View_UpdateEntityVisible();
5440         R_View_UpdateEntityLighting();
5441 }
5442
5443 float viewscalefpsadjusted = 1.0f;
5444
5445 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5446 {
5447         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5448         scale = bound(0.03125f, scale, 1.0f);
5449         *outwidth = (int)ceil(width * scale);
5450         *outheight = (int)ceil(height * scale);
5451 }
5452
5453 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5454 {
5455         const float *customclipplane = NULL;
5456         float plane[4];
5457         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5458         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5459         {
5460                 // LordHavoc: couldn't figure out how to make this approach the
5461                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5462                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5463                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5464                         dist = r_refdef.view.clipplane.dist;
5465                 plane[0] = r_refdef.view.clipplane.normal[0];
5466                 plane[1] = r_refdef.view.clipplane.normal[1];
5467                 plane[2] = r_refdef.view.clipplane.normal[2];
5468                 plane[3] = -dist;
5469                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5470         }
5471
5472         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5473         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5474
5475         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5476         if (!r_refdef.view.useperspective)
5477                 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);
5478         else if (vid.stencil && r_useinfinitefarclip.integer)
5479                 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);
5480         else
5481                 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);
5482         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5483         R_SetViewport(&r_refdef.view.viewport);
5484         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5485         {
5486                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5487                 float screenplane[4];
5488                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5489                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5490                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5491                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5492                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5493         }
5494 }
5495
5496 void R_EntityMatrix(const matrix4x4_t *matrix)
5497 {
5498         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5499         {
5500                 gl_modelmatrixchanged = false;
5501                 gl_modelmatrix = *matrix;
5502                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5503                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5504                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5505                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5506                 CHECKGLERROR
5507                 switch(vid.renderpath)
5508                 {
5509                 case RENDERPATH_D3D9:
5510 #ifdef SUPPORTD3D
5511                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5512                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5513 #endif
5514                         break;
5515                 case RENDERPATH_D3D10:
5516                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5517                         break;
5518                 case RENDERPATH_D3D11:
5519                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5520                         break;
5521                 case RENDERPATH_GL11:
5522                 case RENDERPATH_GL13:
5523                 case RENDERPATH_GLES1:
5524                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5525                         break;
5526                 case RENDERPATH_SOFT:
5527                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5528                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5529                         break;
5530                 case RENDERPATH_GL20:
5531                 case RENDERPATH_GLES2:
5532                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5533                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5534                         break;
5535                 }
5536         }
5537 }
5538
5539 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5540 {
5541         r_viewport_t viewport;
5542
5543         CHECKGLERROR
5544
5545         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5546         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);
5547         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5548         R_SetViewport(&viewport);
5549         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5550         GL_Color(1, 1, 1, 1);
5551         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5552         GL_BlendFunc(GL_ONE, GL_ZERO);
5553         GL_ScissorTest(false);
5554         GL_DepthMask(false);
5555         GL_DepthRange(0, 1);
5556         GL_DepthTest(false);
5557         GL_DepthFunc(GL_LEQUAL);
5558         R_EntityMatrix(&identitymatrix);
5559         R_Mesh_ResetTextureState();
5560         GL_PolygonOffset(0, 0);
5561         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5562         switch(vid.renderpath)
5563         {
5564         case RENDERPATH_GL11:
5565         case RENDERPATH_GL13:
5566         case RENDERPATH_GL20:
5567         case RENDERPATH_GLES1:
5568         case RENDERPATH_GLES2:
5569                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5570                 break;
5571         case RENDERPATH_D3D9:
5572         case RENDERPATH_D3D10:
5573         case RENDERPATH_D3D11:
5574         case RENDERPATH_SOFT:
5575                 break;
5576         }
5577         GL_CullFace(GL_NONE);
5578
5579         CHECKGLERROR
5580 }
5581
5582 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5583 {
5584         DrawQ_Finish();
5585
5586         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5587 }
5588
5589 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5590 {
5591         DrawQ_Finish();
5592
5593         R_SetupView(true, fbo, depthtexture, colortexture);
5594         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5595         GL_Color(1, 1, 1, 1);
5596         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5597         GL_BlendFunc(GL_ONE, GL_ZERO);
5598         GL_ScissorTest(true);
5599         GL_DepthMask(true);
5600         GL_DepthRange(0, 1);
5601         GL_DepthTest(true);
5602         GL_DepthFunc(GL_LEQUAL);
5603         R_EntityMatrix(&identitymatrix);
5604         R_Mesh_ResetTextureState();
5605         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5606         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5607         switch(vid.renderpath)
5608         {
5609         case RENDERPATH_GL11:
5610         case RENDERPATH_GL13:
5611         case RENDERPATH_GL20:
5612         case RENDERPATH_GLES1:
5613         case RENDERPATH_GLES2:
5614                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5615                 break;
5616         case RENDERPATH_D3D9:
5617         case RENDERPATH_D3D10:
5618         case RENDERPATH_D3D11:
5619         case RENDERPATH_SOFT:
5620                 break;
5621         }
5622         GL_CullFace(r_refdef.view.cullface_back);
5623 }
5624
5625 /*
5626 ================
5627 R_RenderView_UpdateViewVectors
5628 ================
5629 */
5630 void R_RenderView_UpdateViewVectors(void)
5631 {
5632         // break apart the view matrix into vectors for various purposes
5633         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5634         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5635         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5636         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5637         // make an inverted copy of the view matrix for tracking sprites
5638         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5639 }
5640
5641 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5642 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5643
5644 static void R_Water_StartFrame(void)
5645 {
5646         int i;
5647         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5648         r_waterstate_waterplane_t *p;
5649         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;
5650
5651         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5652                 return;
5653
5654         switch(vid.renderpath)
5655         {
5656         case RENDERPATH_GL20:
5657         case RENDERPATH_D3D9:
5658         case RENDERPATH_D3D10:
5659         case RENDERPATH_D3D11:
5660         case RENDERPATH_SOFT:
5661         case RENDERPATH_GLES2:
5662                 break;
5663         case RENDERPATH_GL11:
5664         case RENDERPATH_GL13:
5665         case RENDERPATH_GLES1:
5666                 return;
5667         }
5668
5669         // set waterwidth and waterheight to the water resolution that will be
5670         // used (often less than the screen resolution for faster rendering)
5671         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5672
5673         // calculate desired texture sizes
5674         // can't use water if the card does not support the texture size
5675         if (!r_water.integer || r_showsurfaces.integer)
5676                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5677         else if (vid.support.arb_texture_non_power_of_two)
5678         {
5679                 texturewidth = waterwidth;
5680                 textureheight = waterheight;
5681                 camerawidth = waterwidth;
5682                 cameraheight = waterheight;
5683         }
5684         else
5685         {
5686                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5687                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5688                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5689                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5690         }
5691
5692         // allocate textures as needed
5693         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))
5694         {
5695                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5696                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5697                 {
5698                         if (p->texture_refraction)
5699                                 R_FreeTexture(p->texture_refraction);
5700                         p->texture_refraction = NULL;
5701                         if (p->fbo_refraction)
5702                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5703                         p->fbo_refraction = 0;
5704                         if (p->texture_reflection)
5705                                 R_FreeTexture(p->texture_reflection);
5706                         p->texture_reflection = NULL;
5707                         if (p->fbo_reflection)
5708                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5709                         p->fbo_reflection = 0;
5710                         if (p->texture_camera)
5711                                 R_FreeTexture(p->texture_camera);
5712                         p->texture_camera = NULL;
5713                         if (p->fbo_camera)
5714                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5715                         p->fbo_camera = 0;
5716                 }
5717                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5718                 r_fb.water.texturewidth = texturewidth;
5719                 r_fb.water.textureheight = textureheight;
5720                 r_fb.water.camerawidth = camerawidth;
5721                 r_fb.water.cameraheight = cameraheight;
5722         }
5723
5724         if (r_fb.water.texturewidth)
5725         {
5726                 int scaledwidth, scaledheight;
5727
5728                 r_fb.water.enabled = true;
5729
5730                 // water resolution is usually reduced
5731                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5732                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5733                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5734
5735                 // set up variables that will be used in shader setup
5736                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5737                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5738                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5739                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5740         }
5741
5742         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5743         r_fb.water.numwaterplanes = 0;
5744 }
5745
5746 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5747 {
5748         int planeindex, bestplaneindex, vertexindex;
5749         vec3_t mins, maxs, normal, center, v, n;
5750         vec_t planescore, bestplanescore;
5751         mplane_t plane;
5752         r_waterstate_waterplane_t *p;
5753         texture_t *t = R_GetCurrentTexture(surface->texture);
5754
5755         rsurface.texture = t;
5756         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5757         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5758         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5759                 return;
5760         // average the vertex normals, find the surface bounds (after deformvertexes)
5761         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5762         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5763         VectorCopy(n, normal);
5764         VectorCopy(v, mins);
5765         VectorCopy(v, maxs);
5766         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5767         {
5768                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5769                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5770                 VectorAdd(normal, n, normal);
5771                 mins[0] = min(mins[0], v[0]);
5772                 mins[1] = min(mins[1], v[1]);
5773                 mins[2] = min(mins[2], v[2]);
5774                 maxs[0] = max(maxs[0], v[0]);
5775                 maxs[1] = max(maxs[1], v[1]);
5776                 maxs[2] = max(maxs[2], v[2]);
5777         }
5778         VectorNormalize(normal);
5779         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5780
5781         VectorCopy(normal, plane.normal);
5782         VectorNormalize(plane.normal);
5783         plane.dist = DotProduct(center, plane.normal);
5784         PlaneClassify(&plane);
5785         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5786         {
5787                 // skip backfaces (except if nocullface is set)
5788 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5789 //                      return;
5790                 VectorNegate(plane.normal, plane.normal);
5791                 plane.dist *= -1;
5792                 PlaneClassify(&plane);
5793         }
5794
5795
5796         // find a matching plane if there is one
5797         bestplaneindex = -1;
5798         bestplanescore = 1048576.0f;
5799         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5800         {
5801                 if(p->camera_entity == t->camera_entity)
5802                 {
5803                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5804                         if (bestplaneindex < 0 || bestplanescore > planescore)
5805                         {
5806                                 bestplaneindex = planeindex;
5807                                 bestplanescore = planescore;
5808                         }
5809                 }
5810         }
5811         planeindex = bestplaneindex;
5812         p = r_fb.water.waterplanes + planeindex;
5813
5814         // if this surface does not fit any known plane rendered this frame, add one
5815         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5816         {
5817                 // store the new plane
5818                 planeindex = r_fb.water.numwaterplanes++;
5819                 p = r_fb.water.waterplanes + planeindex;
5820                 p->plane = plane;
5821                 // clear materialflags and pvs
5822                 p->materialflags = 0;
5823                 p->pvsvalid = false;
5824                 p->camera_entity = t->camera_entity;
5825                 VectorCopy(mins, p->mins);
5826                 VectorCopy(maxs, p->maxs);
5827         }
5828         else
5829         {
5830                 // merge mins/maxs when we're adding this surface to the plane
5831                 p->mins[0] = min(p->mins[0], mins[0]);
5832                 p->mins[1] = min(p->mins[1], mins[1]);
5833                 p->mins[2] = min(p->mins[2], mins[2]);
5834                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5835                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5836                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5837         }
5838         // merge this surface's materialflags into the waterplane
5839         p->materialflags |= t->currentmaterialflags;
5840         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5841         {
5842                 // merge this surface's PVS into the waterplane
5843                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5844                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5845                 {
5846                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5847                         p->pvsvalid = true;
5848                 }
5849         }
5850 }
5851
5852 extern cvar_t r_drawparticles;
5853 extern cvar_t r_drawdecals;
5854
5855 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5856 {
5857         int myscissor[4];
5858         r_refdef_view_t originalview;
5859         r_refdef_view_t myview;
5860         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;
5861         r_waterstate_waterplane_t *p;
5862         vec3_t visorigin;
5863         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
5864         char vabuf[1024];
5865
5866         originalview = r_refdef.view;
5867
5868         // lowquality hack, temporarily shut down some cvars and restore afterwards
5869         qualityreduction = r_water_lowquality.integer;
5870         if (qualityreduction > 0)
5871         {
5872                 if (qualityreduction >= 1)
5873                 {
5874                         old_r_shadows = r_shadows.integer;
5875                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5876                         old_r_dlight = r_shadow_realtime_dlight.integer;
5877                         Cvar_SetValueQuick(&r_shadows, 0);
5878                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5879                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5880                 }
5881                 if (qualityreduction >= 2)
5882                 {
5883                         old_r_dynamic = r_dynamic.integer;
5884                         old_r_particles = r_drawparticles.integer;
5885                         old_r_decals = r_drawdecals.integer;
5886                         Cvar_SetValueQuick(&r_dynamic, 0);
5887                         Cvar_SetValueQuick(&r_drawparticles, 0);
5888                         Cvar_SetValueQuick(&r_drawdecals, 0);
5889                 }
5890         }
5891
5892         // make sure enough textures are allocated
5893         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5894         {
5895                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5896                 {
5897                         if (!p->texture_refraction)
5898                                 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);
5899                         if (!p->texture_refraction)
5900                                 goto error;
5901                         if (usewaterfbo)
5902                         {
5903                                 if (r_fb.water.depthtexture == NULL)
5904                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5905                                 if (p->fbo_refraction == 0)
5906                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5907                         }
5908                 }
5909                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5910                 {
5911                         if (!p->texture_camera)
5912                                 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);
5913                         if (!p->texture_camera)
5914                                 goto error;
5915                         if (usewaterfbo)
5916                         {
5917                                 if (r_fb.water.depthtexture == NULL)
5918                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5919                                 if (p->fbo_camera == 0)
5920                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5921                         }
5922                 }
5923
5924                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5925                 {
5926                         if (!p->texture_reflection)
5927                                 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);
5928                         if (!p->texture_reflection)
5929                                 goto error;
5930                         if (usewaterfbo)
5931                         {
5932                                 if (r_fb.water.depthtexture == NULL)
5933                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5934                                 if (p->fbo_reflection == 0)
5935                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5936                         }
5937                 }
5938         }
5939
5940         // render views
5941         r_refdef.view = originalview;
5942         r_refdef.view.showdebug = false;
5943         r_refdef.view.width = r_fb.water.waterwidth;
5944         r_refdef.view.height = r_fb.water.waterheight;
5945         r_refdef.view.useclipplane = true;
5946         myview = r_refdef.view;
5947         r_fb.water.renderingscene = true;
5948         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5949         {
5950                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5951                 {
5952                         r_refdef.view = myview;
5953                         if(r_water_scissormode.integer)
5954                         {
5955                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5956                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5957                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5958                         }
5959
5960                         // render reflected scene and copy into texture
5961                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5962                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5963                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5964                         r_refdef.view.clipplane = p->plane;
5965                         // reverse the cullface settings for this render
5966                         r_refdef.view.cullface_front = GL_FRONT;
5967                         r_refdef.view.cullface_back = GL_BACK;
5968                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5969                         {
5970                                 r_refdef.view.usecustompvs = true;
5971                                 if (p->pvsvalid)
5972                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5973                                 else
5974                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5975                         }
5976
5977                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5978                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5979                         R_ClearScreen(r_refdef.fogenabled);
5980                         if(r_water_scissormode.integer & 2)
5981                                 R_View_UpdateWithScissor(myscissor);
5982                         else
5983                                 R_View_Update();
5984                         R_AnimCache_CacheVisibleEntities();
5985                         if(r_water_scissormode.integer & 1)
5986                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5987                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5988
5989                         if (!p->fbo_reflection)
5990                                 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);
5991                         r_fb.water.hideplayer = false;
5992                 }
5993
5994                 // render the normal view scene and copy into texture
5995                 // (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)
5996                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5997                 {
5998                         r_refdef.view = myview;
5999                         if(r_water_scissormode.integer)
6000                         {
6001                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6002                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
6003                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
6004                         }
6005
6006                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
6007
6008                         r_refdef.view.clipplane = p->plane;
6009                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6010                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6011
6012                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
6013                         {
6014                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6015                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
6016                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6017                                 R_RenderView_UpdateViewVectors();
6018                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6019                                 {
6020                                         r_refdef.view.usecustompvs = true;
6021                                         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);
6022                                 }
6023                         }
6024
6025                         PlaneClassify(&r_refdef.view.clipplane);
6026
6027                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6028                         R_ClearScreen(r_refdef.fogenabled);
6029                         if(r_water_scissormode.integer & 2)
6030                                 R_View_UpdateWithScissor(myscissor);
6031                         else
6032                                 R_View_Update();
6033                         R_AnimCache_CacheVisibleEntities();
6034                         if(r_water_scissormode.integer & 1)
6035                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
6036                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
6037
6038                         if (!p->fbo_refraction)
6039                                 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);
6040                         r_fb.water.hideplayer = false;
6041                 }
6042                 else if (p->materialflags & MATERIALFLAG_CAMERA)
6043                 {
6044                         r_refdef.view = myview;
6045
6046                         r_refdef.view.clipplane = p->plane;
6047                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
6048                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
6049
6050                         r_refdef.view.width = r_fb.water.camerawidth;
6051                         r_refdef.view.height = r_fb.water.cameraheight;
6052                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
6053                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
6054                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
6055                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
6056
6057                         if(p->camera_entity)
6058                         {
6059                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
6060                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
6061                         }
6062
6063                         // note: all of the view is used for displaying... so
6064                         // there is no use in scissoring
6065
6066                         // reverse the cullface settings for this render
6067                         r_refdef.view.cullface_front = GL_FRONT;
6068                         r_refdef.view.cullface_back = GL_BACK;
6069                         // also reverse the view matrix
6070                         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
6071                         R_RenderView_UpdateViewVectors();
6072                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
6073                         {
6074                                 r_refdef.view.usecustompvs = true;
6075                                 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);
6076                         }
6077                         
6078                         // camera needs no clipplane
6079                         r_refdef.view.useclipplane = false;
6080
6081                         PlaneClassify(&r_refdef.view.clipplane);
6082
6083                         r_fb.water.hideplayer = false;
6084
6085                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6086                         R_ClearScreen(r_refdef.fogenabled);
6087                         R_View_Update();
6088                         R_AnimCache_CacheVisibleEntities();
6089                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
6090
6091                         if (!p->fbo_camera)
6092                                 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);
6093                         r_fb.water.hideplayer = false;
6094                 }
6095
6096         }
6097         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
6098         r_fb.water.renderingscene = false;
6099         r_refdef.view = originalview;
6100         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6101         if (!r_fb.water.depthtexture)
6102                 R_ClearScreen(r_refdef.fogenabled);
6103         R_View_Update();
6104         R_AnimCache_CacheVisibleEntities();
6105         goto finish;
6106 error:
6107         r_refdef.view = originalview;
6108         r_fb.water.renderingscene = false;
6109         Cvar_SetValueQuick(&r_water, 0);
6110         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
6111 finish:
6112         // lowquality hack, restore cvars
6113         if (qualityreduction > 0)
6114         {
6115                 if (qualityreduction >= 1)
6116                 {
6117                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
6118                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
6119                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
6120                 }
6121                 if (qualityreduction >= 2)
6122                 {
6123                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
6124                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
6125                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
6126                 }
6127         }
6128 }
6129
6130 static void R_Bloom_StartFrame(void)
6131 {
6132         int i;
6133         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6134         int viewwidth, viewheight;
6135         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two && vid.samples < 2;
6136         textype_t textype = TEXTYPE_COLORBUFFER;
6137
6138         switch (vid.renderpath)
6139         {
6140         case RENDERPATH_GL20:
6141                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6142                 if (vid.support.ext_framebuffer_object && vid.support.arb_texture_non_power_of_two)
6143                 {
6144                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6145                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6146                 }
6147                 break;
6148         case RENDERPATH_GL11:
6149         case RENDERPATH_GL13:
6150         case RENDERPATH_GLES1:
6151         case RENDERPATH_GLES2:
6152         case RENDERPATH_D3D9:
6153         case RENDERPATH_D3D10:
6154         case RENDERPATH_D3D11:
6155                 r_fb.usedepthtextures = false;
6156                 break;
6157         case RENDERPATH_SOFT:
6158                 r_fb.usedepthtextures = true;
6159                 break;
6160         }
6161
6162         if (r_viewscale_fpsscaling.integer)
6163         {
6164                 double actualframetime;
6165                 double targetframetime;
6166                 double adjust;
6167                 actualframetime = r_refdef.lastdrawscreentime;
6168                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6169                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6170                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6171                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6172                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6173                 viewscalefpsadjusted += adjust;
6174                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6175         }
6176         else
6177                 viewscalefpsadjusted = 1.0f;
6178
6179         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6180
6181         switch(vid.renderpath)
6182         {
6183         case RENDERPATH_GL20:
6184         case RENDERPATH_D3D9:
6185         case RENDERPATH_D3D10:
6186         case RENDERPATH_D3D11:
6187         case RENDERPATH_SOFT:
6188         case RENDERPATH_GLES2:
6189                 break;
6190         case RENDERPATH_GL11:
6191         case RENDERPATH_GL13:
6192         case RENDERPATH_GLES1:
6193                 return;
6194         }
6195
6196         // set bloomwidth and bloomheight to the bloom resolution that will be
6197         // used (often less than the screen resolution for faster rendering)
6198         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6199         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6200         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6201         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6202         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6203
6204         // calculate desired texture sizes
6205         if (vid.support.arb_texture_non_power_of_two)
6206         {
6207                 screentexturewidth = vid.width;
6208                 screentextureheight = vid.height;
6209                 bloomtexturewidth = r_fb.bloomwidth;
6210                 bloomtextureheight = r_fb.bloomheight;
6211         }
6212         else
6213         {
6214                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6215                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6216                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6217                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6218         }
6219
6220         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))
6221         {
6222                 Cvar_SetValueQuick(&r_bloom, 0);
6223                 Cvar_SetValueQuick(&r_motionblur, 0);
6224                 Cvar_SetValueQuick(&r_damageblur, 0);
6225         }
6226
6227         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6228          && !r_bloom.integer
6229          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6230          && !useviewfbo
6231          && r_viewscale.value == 1.0f
6232          && !r_viewscale_fpsscaling.integer)
6233                 screentexturewidth = screentextureheight = 0;
6234         if (!r_bloom.integer)
6235                 bloomtexturewidth = bloomtextureheight = 0;
6236
6237         // allocate textures as needed
6238         if (r_fb.screentexturewidth != screentexturewidth
6239          || r_fb.screentextureheight != screentextureheight
6240          || r_fb.bloomtexturewidth != bloomtexturewidth
6241          || r_fb.bloomtextureheight != bloomtextureheight
6242          || r_fb.textype != textype
6243          || useviewfbo != (r_fb.fbo != 0))
6244         {
6245                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6246                 {
6247                         if (r_fb.bloomtexture[i])
6248                                 R_FreeTexture(r_fb.bloomtexture[i]);
6249                         r_fb.bloomtexture[i] = NULL;
6250
6251                         if (r_fb.bloomfbo[i])
6252                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6253                         r_fb.bloomfbo[i] = 0;
6254                 }
6255
6256                 if (r_fb.fbo)
6257                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6258                 r_fb.fbo = 0;
6259
6260                 if (r_fb.colortexture)
6261                         R_FreeTexture(r_fb.colortexture);
6262                 r_fb.colortexture = NULL;
6263
6264                 if (r_fb.depthtexture)
6265                         R_FreeTexture(r_fb.depthtexture);
6266                 r_fb.depthtexture = NULL;
6267
6268                 if (r_fb.ghosttexture)
6269                         R_FreeTexture(r_fb.ghosttexture);
6270                 r_fb.ghosttexture = NULL;
6271
6272                 r_fb.screentexturewidth = screentexturewidth;
6273                 r_fb.screentextureheight = screentextureheight;
6274                 r_fb.bloomtexturewidth = bloomtexturewidth;
6275                 r_fb.bloomtextureheight = bloomtextureheight;
6276                 r_fb.textype = textype;
6277
6278                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6279                 {
6280                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6281                                 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);
6282                         r_fb.ghosttexture_valid = false;
6283                         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);
6284                         if (useviewfbo)
6285                         {
6286                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6287                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6288                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6289                         }
6290                 }
6291
6292                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6293                 {
6294                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6295                         {
6296                                 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);
6297                                 if (useviewfbo)
6298                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6299                         }
6300                 }
6301         }
6302
6303         // bloom texture is a different resolution
6304         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6305         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6306         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6307         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6308         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6309
6310         // set up a texcoord array for the full resolution screen image
6311         // (we have to keep this around to copy back during final render)
6312         r_fb.screentexcoord2f[0] = 0;
6313         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6314         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6315         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6316         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6317         r_fb.screentexcoord2f[5] = 0;
6318         r_fb.screentexcoord2f[6] = 0;
6319         r_fb.screentexcoord2f[7] = 0;
6320
6321         if(r_fb.fbo) 
6322         {
6323                 for (i = 1;i < 8;i += 2)
6324                 {
6325                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6326                 }
6327         }
6328
6329         // set up a texcoord array for the reduced resolution bloom image
6330         // (which will be additive blended over the screen image)
6331         r_fb.bloomtexcoord2f[0] = 0;
6332         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6333         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6334         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6335         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6336         r_fb.bloomtexcoord2f[5] = 0;
6337         r_fb.bloomtexcoord2f[6] = 0;
6338         r_fb.bloomtexcoord2f[7] = 0;
6339
6340         switch(vid.renderpath)
6341         {
6342         case RENDERPATH_GL11:
6343         case RENDERPATH_GL13:
6344         case RENDERPATH_GL20:
6345         case RENDERPATH_SOFT:
6346         case RENDERPATH_GLES1:
6347         case RENDERPATH_GLES2:
6348                 break;
6349         case RENDERPATH_D3D9:
6350         case RENDERPATH_D3D10:
6351         case RENDERPATH_D3D11:
6352                 for (i = 0;i < 4;i++)
6353                 {
6354                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6355                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6356                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6357                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6358                 }
6359                 break;
6360         }
6361
6362         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6363
6364         if (r_fb.fbo)
6365                 r_refdef.view.clear = true;
6366 }
6367
6368 static void R_Bloom_MakeTexture(void)
6369 {
6370         int x, range, dir;
6371         float xoffset, yoffset, r, brighten;
6372         rtexture_t *intex;
6373         float colorscale = r_bloom_colorscale.value;
6374
6375         r_refdef.stats.bloom++;
6376     
6377 #if 0
6378     // this copy is unnecessary since it happens in R_BlendView already
6379         if (!r_fb.fbo)
6380         {
6381                 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);
6382                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6383         }
6384 #endif
6385
6386         // scale down screen texture to the bloom texture size
6387         CHECKGLERROR
6388         r_fb.bloomindex = 0;
6389         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6390         R_SetViewport(&r_fb.bloomviewport);
6391         GL_DepthTest(false);
6392         GL_BlendFunc(GL_ONE, GL_ZERO);
6393         GL_Color(colorscale, colorscale, colorscale, 1);
6394         // 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...
6395         switch(vid.renderpath)
6396         {
6397         case RENDERPATH_GL11:
6398         case RENDERPATH_GL13:
6399         case RENDERPATH_GL20:
6400         case RENDERPATH_GLES1:
6401         case RENDERPATH_GLES2:
6402         case RENDERPATH_SOFT:
6403                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6404                 break;
6405         case RENDERPATH_D3D9:
6406         case RENDERPATH_D3D10:
6407         case RENDERPATH_D3D11:
6408                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6409                 break;
6410         }
6411         // TODO: do boxfilter scale-down in shader?
6412         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6413         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6414         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6415
6416         // we now have a properly scaled bloom image
6417         if (!r_fb.bloomfbo[r_fb.bloomindex])
6418         {
6419                 // copy it into the bloom texture
6420                 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);
6421                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6422         }
6423
6424         // multiply bloom image by itself as many times as desired
6425         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6426         {
6427                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6428                 r_fb.bloomindex ^= 1;
6429                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6430                 x *= 2;
6431                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6432                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6433                 {
6434                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6435                         GL_Color(r,r,r,1); // apply fix factor
6436                 }
6437                 else
6438                 {
6439                         if(x <= 2)
6440                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6441                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6442                         GL_Color(1,1,1,1); // no fix factor supported here
6443                 }
6444                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6445                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6446                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6447                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6448
6449                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6450                 {
6451                         // copy the darkened image to a texture
6452                         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);
6453                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6454                 }
6455         }
6456
6457         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6458         brighten = r_bloom_brighten.value;
6459         brighten = sqrt(brighten);
6460         if(range >= 1)
6461                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6462
6463         for (dir = 0;dir < 2;dir++)
6464         {
6465                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6466                 r_fb.bloomindex ^= 1;
6467                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6468                 // blend on at multiple vertical offsets to achieve a vertical blur
6469                 // TODO: do offset blends using GLSL
6470                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6471                 GL_BlendFunc(GL_ONE, GL_ZERO);
6472                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6473                 for (x = -range;x <= range;x++)
6474                 {
6475                         if (!dir){xoffset = 0;yoffset = x;}
6476                         else {xoffset = x;yoffset = 0;}
6477                         xoffset /= (float)r_fb.bloomtexturewidth;
6478                         yoffset /= (float)r_fb.bloomtextureheight;
6479                         // compute a texcoord array with the specified x and y offset
6480                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6481                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6482                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6483                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6484                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6485                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6486                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6487                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6488                         // this r value looks like a 'dot' particle, fading sharply to
6489                         // black at the edges
6490                         // (probably not realistic but looks good enough)
6491                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6492                         //r = brighten/(range*2+1);
6493                         r = brighten / (range * 2 + 1);
6494                         if(range >= 1)
6495                                 r *= (1 - x*x/(float)(range*range));
6496                         GL_Color(r, r, r, 1);
6497                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6498                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6499                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6500                         GL_BlendFunc(GL_ONE, GL_ONE);
6501                 }
6502
6503                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6504                 {
6505                         // copy the vertically or horizontally blurred bloom view to a texture
6506                         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);
6507                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6508                 }
6509         }
6510 }
6511
6512 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6513 {
6514         unsigned int permutation;
6515         float uservecs[4][4];
6516
6517         R_EntityMatrix(&identitymatrix);
6518
6519         switch (vid.renderpath)
6520         {
6521         case RENDERPATH_GL20:
6522         case RENDERPATH_D3D9:
6523         case RENDERPATH_D3D10:
6524         case RENDERPATH_D3D11:
6525         case RENDERPATH_SOFT:
6526         case RENDERPATH_GLES2:
6527                 permutation =
6528                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6529                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6530                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6531                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6532                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6533
6534                 if (r_fb.colortexture)
6535                 {
6536                         if (!r_fb.fbo)
6537                         {
6538                                 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);
6539                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6540                         }
6541
6542                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6543                         {
6544                                 // declare variables
6545                                 float blur_factor, blur_mouseaccel, blur_velocity;
6546                                 static float blur_average; 
6547                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6548
6549                                 // set a goal for the factoring
6550                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6551                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6552                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6553                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6554                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6555                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6556
6557                                 // from the goal, pick an averaged value between goal and last value
6558                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6559                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6560
6561                                 // enforce minimum amount of blur 
6562                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6563
6564                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6565
6566                                 // calculate values into a standard alpha
6567                                 cl.motionbluralpha = 1 - exp(-
6568                                                 (
6569                                                  (r_motionblur.value * blur_factor / 80)
6570                                                  +
6571                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6572                                                 )
6573                                                 /
6574                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6575                                           );
6576
6577                                 // randomization for the blur value to combat persistent ghosting
6578                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6579                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6580
6581                                 // apply the blur
6582                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6583                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6584                                 {
6585                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6586                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6587                                         switch(vid.renderpath)
6588                                         {
6589                                         case RENDERPATH_GL11:
6590                                         case RENDERPATH_GL13:
6591                                         case RENDERPATH_GL20:
6592                                         case RENDERPATH_GLES1:
6593                                         case RENDERPATH_GLES2:
6594                                         case RENDERPATH_SOFT:
6595                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6596                                                 break;
6597                                         case RENDERPATH_D3D9:
6598                                         case RENDERPATH_D3D10:
6599                                         case RENDERPATH_D3D11:
6600                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6601                                                 break;
6602                                         }
6603                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6604                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6605                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6606                                 }
6607
6608                                 // updates old view angles for next pass
6609                                 VectorCopy(cl.viewangles, blur_oldangles);
6610
6611                                 // copy view into the ghost texture
6612                                 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);
6613                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6614                                 r_fb.ghosttexture_valid = true;
6615                         }
6616                 }
6617                 else
6618                 {
6619                         // no r_fb.colortexture means we're rendering to the real fb
6620                         // we may still have to do view tint...
6621                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6622                         {
6623                                 // apply a color tint to the whole view
6624                                 R_ResetViewRendering2D(0, NULL, NULL);
6625                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6626                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6627                                 R_SetupShader_Generic_NoTexture(false, true);
6628                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6629                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6630                         }
6631                         break; // no screen processing, no bloom, skip it
6632                 }
6633
6634                 if (r_fb.bloomtexture[0])
6635                 {
6636                         // make the bloom texture
6637                         R_Bloom_MakeTexture();
6638                 }
6639
6640 #if _MSC_VER >= 1400
6641 #define sscanf sscanf_s
6642 #endif
6643                 memset(uservecs, 0, sizeof(uservecs));
6644                 if (r_glsl_postprocess_uservec1_enable.integer)
6645                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6646                 if (r_glsl_postprocess_uservec2_enable.integer)
6647                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6648                 if (r_glsl_postprocess_uservec3_enable.integer)
6649                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6650                 if (r_glsl_postprocess_uservec4_enable.integer)
6651                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6652
6653                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6654                 GL_Color(1, 1, 1, 1);
6655                 GL_BlendFunc(GL_ONE, GL_ZERO);
6656
6657                 switch(vid.renderpath)
6658                 {
6659                 case RENDERPATH_GL20:
6660                 case RENDERPATH_GLES2:
6661                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6662                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6663                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6664                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6665                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6666                         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]);
6667                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6668                         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]);
6669                         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]);
6670                         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]);
6671                         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]);
6672                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6673                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6674                         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);
6675                         break;
6676                 case RENDERPATH_D3D9:
6677 #ifdef SUPPORTD3D
6678                         // 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...
6679                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6680                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6681                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6682                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6683                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6684                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6685                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6686                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6687                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6688                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6689                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6690                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6691                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6692                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6693 #endif
6694                         break;
6695                 case RENDERPATH_D3D10:
6696                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6697                         break;
6698                 case RENDERPATH_D3D11:
6699                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6700                         break;
6701                 case RENDERPATH_SOFT:
6702                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6703                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6704                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6705                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6706                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6707                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6708                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6709                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6710                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6711                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6712                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6713                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6714                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6715                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6716                         break;
6717                 default:
6718                         break;
6719                 }
6720                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6721                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6722                 break;
6723         case RENDERPATH_GL11:
6724         case RENDERPATH_GL13:
6725         case RENDERPATH_GLES1:
6726                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6727                 {
6728                         // apply a color tint to the whole view
6729                         R_ResetViewRendering2D(0, NULL, NULL);
6730                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6731                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6732                         R_SetupShader_Generic_NoTexture(false, true);
6733                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6734                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6735                 }
6736                 break;
6737         }
6738 }
6739
6740 matrix4x4_t r_waterscrollmatrix;
6741
6742 void R_UpdateFog(void)
6743 {
6744         // Nehahra fog
6745         if (gamemode == GAME_NEHAHRA)
6746         {
6747                 if (gl_fogenable.integer)
6748                 {
6749                         r_refdef.oldgl_fogenable = true;
6750                         r_refdef.fog_density = gl_fogdensity.value;
6751                         r_refdef.fog_red = gl_fogred.value;
6752                         r_refdef.fog_green = gl_foggreen.value;
6753                         r_refdef.fog_blue = gl_fogblue.value;
6754                         r_refdef.fog_alpha = 1;
6755                         r_refdef.fog_start = 0;
6756                         r_refdef.fog_end = gl_skyclip.value;
6757                         r_refdef.fog_height = 1<<30;
6758                         r_refdef.fog_fadedepth = 128;
6759                 }
6760                 else if (r_refdef.oldgl_fogenable)
6761                 {
6762                         r_refdef.oldgl_fogenable = false;
6763                         r_refdef.fog_density = 0;
6764                         r_refdef.fog_red = 0;
6765                         r_refdef.fog_green = 0;
6766                         r_refdef.fog_blue = 0;
6767                         r_refdef.fog_alpha = 0;
6768                         r_refdef.fog_start = 0;
6769                         r_refdef.fog_end = 0;
6770                         r_refdef.fog_height = 1<<30;
6771                         r_refdef.fog_fadedepth = 128;
6772                 }
6773         }
6774
6775         // fog parms
6776         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6777         r_refdef.fog_start = max(0, r_refdef.fog_start);
6778         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6779
6780         if (r_refdef.fog_density && r_drawfog.integer)
6781         {
6782                 r_refdef.fogenabled = true;
6783                 // this is the point where the fog reaches 0.9986 alpha, which we
6784                 // consider a good enough cutoff point for the texture
6785                 // (0.9986 * 256 == 255.6)
6786                 if (r_fog_exp2.integer)
6787                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6788                 else
6789                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6790                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6791                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6792                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6793                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6794                         R_BuildFogHeightTexture();
6795                 // fog color was already set
6796                 // update the fog texture
6797                 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)
6798                         R_BuildFogTexture();
6799                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6800                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6801         }
6802         else
6803                 r_refdef.fogenabled = false;
6804
6805         // fog color
6806         if (r_refdef.fog_density)
6807         {
6808                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6809                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6810                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6811
6812                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6813                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6814                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6815                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6816
6817                 {
6818                         vec3_t fogvec;
6819                         VectorCopy(r_refdef.fogcolor, fogvec);
6820                         //   color.rgb *= ContrastBoost * SceneBrightness;
6821                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6822                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6823                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6824                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6825                 }
6826         }
6827 }
6828
6829 void R_UpdateVariables(void)
6830 {
6831         R_Textures_Frame();
6832
6833         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6834
6835         r_refdef.farclip = r_farclip_base.value;
6836         if (r_refdef.scene.worldmodel)
6837                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6838         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6839
6840         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6841                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6842         r_refdef.polygonfactor = 0;
6843         r_refdef.polygonoffset = 0;
6844         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6845         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6846
6847         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6848         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6849         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6850         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6851         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6852         if (FAKELIGHT_ENABLED)
6853         {
6854                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6855         }
6856         else if (r_refdef.scene.worldmodel)
6857         {
6858                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6859         }
6860         if (r_showsurfaces.integer)
6861         {
6862                 r_refdef.scene.rtworld = false;
6863                 r_refdef.scene.rtworldshadows = false;
6864                 r_refdef.scene.rtdlight = false;
6865                 r_refdef.scene.rtdlightshadows = false;
6866                 r_refdef.lightmapintensity = 0;
6867         }
6868
6869         switch(vid.renderpath)
6870         {
6871         case RENDERPATH_GL20:
6872         case RENDERPATH_D3D9:
6873         case RENDERPATH_D3D10:
6874         case RENDERPATH_D3D11:
6875         case RENDERPATH_SOFT:
6876         case RENDERPATH_GLES2:
6877                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6878                 {
6879                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6880                         {
6881                                 // build GLSL gamma texture
6882 #define RAMPWIDTH 256
6883                                 unsigned short ramp[RAMPWIDTH * 3];
6884                                 unsigned char rampbgr[RAMPWIDTH][4];
6885                                 int i;
6886
6887                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6888
6889                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6890                                 for(i = 0; i < RAMPWIDTH; ++i)
6891                                 {
6892                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6893                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6894                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6895                                         rampbgr[i][3] = 0;
6896                                 }
6897                                 if (r_texture_gammaramps)
6898                                 {
6899                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6900                                 }
6901                                 else
6902                                 {
6903                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6904                                 }
6905                         }
6906                 }
6907                 else
6908                 {
6909                         // remove GLSL gamma texture
6910                 }
6911                 break;
6912         case RENDERPATH_GL11:
6913         case RENDERPATH_GL13:
6914         case RENDERPATH_GLES1:
6915                 break;
6916         }
6917 }
6918
6919 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6920 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6921 /*
6922 ================
6923 R_SelectScene
6924 ================
6925 */
6926 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6927         if( scenetype != r_currentscenetype ) {
6928                 // store the old scenetype
6929                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6930                 r_currentscenetype = scenetype;
6931                 // move in the new scene
6932                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6933         }
6934 }
6935
6936 /*
6937 ================
6938 R_GetScenePointer
6939 ================
6940 */
6941 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6942 {
6943         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6944         if( scenetype == r_currentscenetype ) {
6945                 return &r_refdef.scene;
6946         } else {
6947                 return &r_scenes_store[ scenetype ];
6948         }
6949 }
6950
6951 static int R_SortEntities_Compare(const void *ap, const void *bp)
6952 {
6953         const entity_render_t *a = *(const entity_render_t **)ap;
6954         const entity_render_t *b = *(const entity_render_t **)bp;
6955
6956         // 1. compare model
6957         if(a->model < b->model)
6958                 return -1;
6959         if(a->model > b->model)
6960                 return +1;
6961
6962         // 2. compare skin
6963         // TODO possibly calculate the REAL skinnum here first using
6964         // skinscenes?
6965         if(a->skinnum < b->skinnum)
6966                 return -1;
6967         if(a->skinnum > b->skinnum)
6968                 return +1;
6969
6970         // everything we compared is equal
6971         return 0;
6972 }
6973 static void R_SortEntities(void)
6974 {
6975         // below or equal 2 ents, sorting never gains anything
6976         if(r_refdef.scene.numentities <= 2)
6977                 return;
6978         // sort
6979         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6980 }
6981
6982 /*
6983 ================
6984 R_RenderView
6985 ================
6986 */
6987 int dpsoftrast_test;
6988 extern cvar_t r_shadow_bouncegrid;
6989 void R_RenderView(void)
6990 {
6991         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6992         int fbo;
6993         rtexture_t *depthtexture;
6994         rtexture_t *colortexture;
6995
6996         dpsoftrast_test = r_test.integer;
6997
6998         if (r_timereport_active)
6999                 R_TimeReport("start");
7000         r_textureframe++; // used only by R_GetCurrentTexture
7001         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
7002
7003         if(R_CompileShader_CheckStaticParms())
7004                 R_GLSL_Restart_f();
7005
7006         if (!r_drawentities.integer)
7007                 r_refdef.scene.numentities = 0;
7008         else if (r_sortentities.integer)
7009                 R_SortEntities();
7010
7011         R_AnimCache_ClearCache();
7012         R_FrameData_NewFrame();
7013
7014         /* adjust for stereo display */
7015         if(R_Stereo_Active())
7016         {
7017                 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);
7018                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
7019         }
7020
7021         if (r_refdef.view.isoverlay)
7022         {
7023                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
7024                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
7025                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
7026                 R_TimeReport("depthclear");
7027
7028                 r_refdef.view.showdebug = false;
7029
7030                 r_fb.water.enabled = false;
7031                 r_fb.water.numwaterplanes = 0;
7032
7033                 R_RenderScene(0, NULL, NULL);
7034
7035                 r_refdef.view.matrix = originalmatrix;
7036
7037                 CHECKGLERROR
7038                 return;
7039         }
7040
7041         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
7042         {
7043                 r_refdef.view.matrix = originalmatrix;
7044                 return;
7045         }
7046
7047         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
7048
7049         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
7050                 // in sRGB fallback, behave similar to true sRGB: convert this
7051                 // value from linear to sRGB
7052                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
7053
7054         R_RenderView_UpdateViewVectors();
7055
7056         R_Shadow_UpdateWorldLightSelection();
7057
7058         R_Bloom_StartFrame();
7059
7060         // apply bloom brightness offset
7061         if(r_fb.bloomtexture[0])
7062                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
7063
7064         R_Water_StartFrame();
7065
7066         // now we probably have an fbo to render into
7067         fbo = r_fb.fbo;
7068         depthtexture = r_fb.depthtexture;
7069         colortexture = r_fb.colortexture;
7070
7071         CHECKGLERROR
7072         if (r_timereport_active)
7073                 R_TimeReport("viewsetup");
7074
7075         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7076
7077         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
7078         {
7079                 R_ClearScreen(r_refdef.fogenabled);
7080                 if (r_timereport_active)
7081                         R_TimeReport("viewclear");
7082         }
7083         r_refdef.view.clear = true;
7084
7085         r_refdef.view.showdebug = true;
7086
7087         R_View_Update();
7088         if (r_timereport_active)
7089                 R_TimeReport("visibility");
7090
7091         R_AnimCache_CacheVisibleEntities();
7092         if (r_timereport_active)
7093                 R_TimeReport("animcache");
7094
7095         R_Shadow_UpdateBounceGridTexture();
7096         if (r_timereport_active && r_shadow_bouncegrid.integer)
7097                 R_TimeReport("bouncegrid");
7098
7099         r_fb.water.numwaterplanes = 0;
7100         if (r_fb.water.enabled)
7101                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
7102
7103         R_RenderScene(fbo, depthtexture, colortexture);
7104         r_fb.water.numwaterplanes = 0;
7105
7106         R_BlendView(fbo, depthtexture, colortexture);
7107         if (r_timereport_active)
7108                 R_TimeReport("blendview");
7109
7110         GL_Scissor(0, 0, vid.width, vid.height);
7111         GL_ScissorTest(false);
7112
7113         r_refdef.view.matrix = originalmatrix;
7114
7115         CHECKGLERROR
7116 }
7117
7118 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7119 {
7120         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
7121         {
7122                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
7123                 if (r_timereport_active)
7124                         R_TimeReport("waterworld");
7125         }
7126
7127         // don't let sound skip if going slow
7128         if (r_refdef.scene.extraupdate)
7129                 S_ExtraUpdate ();
7130
7131         R_DrawModelsAddWaterPlanes();
7132         if (r_timereport_active)
7133                 R_TimeReport("watermodels");
7134
7135         if (r_fb.water.numwaterplanes)
7136         {
7137                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7138                 if (r_timereport_active)
7139                         R_TimeReport("waterscenes");
7140         }
7141 }
7142
7143 extern cvar_t cl_locs_show;
7144 static void R_DrawLocs(void);
7145 static void R_DrawEntityBBoxes(void);
7146 static void R_DrawModelDecals(void);
7147 extern cvar_t cl_decals_newsystem;
7148 extern qboolean r_shadow_usingdeferredprepass;
7149 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7150 {
7151         qboolean shadowmapping = false;
7152
7153         if (r_timereport_active)
7154                 R_TimeReport("beginscene");
7155
7156         r_refdef.stats.renders++;
7157
7158         R_UpdateFog();
7159
7160         // don't let sound skip if going slow
7161         if (r_refdef.scene.extraupdate)
7162                 S_ExtraUpdate ();
7163
7164         R_MeshQueue_BeginScene();
7165
7166         R_SkyStartFrame();
7167
7168         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);
7169
7170         if (r_timereport_active)
7171                 R_TimeReport("skystartframe");
7172
7173         if (cl.csqc_vidvars.drawworld)
7174         {
7175                 // don't let sound skip if going slow
7176                 if (r_refdef.scene.extraupdate)
7177                         S_ExtraUpdate ();
7178
7179                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7180                 {
7181                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7182                         if (r_timereport_active)
7183                                 R_TimeReport("worldsky");
7184                 }
7185
7186                 if (R_DrawBrushModelsSky() && r_timereport_active)
7187                         R_TimeReport("bmodelsky");
7188
7189                 if (skyrendermasked && skyrenderlater)
7190                 {
7191                         // we have to force off the water clipping plane while rendering sky
7192                         R_SetupView(false, fbo, depthtexture, colortexture);
7193                         R_Sky();
7194                         R_SetupView(true, fbo, depthtexture, colortexture);
7195                         if (r_timereport_active)
7196                                 R_TimeReport("sky");
7197                 }
7198         }
7199
7200         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7201         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7202                 R_Shadow_PrepareModelShadows();
7203         if (r_timereport_active)
7204                 R_TimeReport("preparelights");
7205
7206         if (R_Shadow_ShadowMappingEnabled())
7207                 shadowmapping = true;
7208
7209         if (r_shadow_usingdeferredprepass)
7210                 R_Shadow_DrawPrepass();
7211
7212         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7213         {
7214                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7215                 if (r_timereport_active)
7216                         R_TimeReport("worlddepth");
7217         }
7218         if (r_depthfirst.integer >= 2)
7219         {
7220                 R_DrawModelsDepth();
7221                 if (r_timereport_active)
7222                         R_TimeReport("modeldepth");
7223         }
7224
7225         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7226         {
7227                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7228                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7229                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7230                 // don't let sound skip if going slow
7231                 if (r_refdef.scene.extraupdate)
7232                         S_ExtraUpdate ();
7233         }
7234
7235         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7236         {
7237                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7238                 if (r_timereport_active)
7239                         R_TimeReport("world");
7240         }
7241
7242         // don't let sound skip if going slow
7243         if (r_refdef.scene.extraupdate)
7244                 S_ExtraUpdate ();
7245
7246         R_DrawModels();
7247         if (r_timereport_active)
7248                 R_TimeReport("models");
7249
7250         // don't let sound skip if going slow
7251         if (r_refdef.scene.extraupdate)
7252                 S_ExtraUpdate ();
7253
7254         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7255         {
7256                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7257                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7258                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7259                 // don't let sound skip if going slow
7260                 if (r_refdef.scene.extraupdate)
7261                         S_ExtraUpdate ();
7262         }
7263
7264         if (!r_shadow_usingdeferredprepass)
7265         {
7266                 R_Shadow_DrawLights();
7267                 if (r_timereport_active)
7268                         R_TimeReport("rtlights");
7269         }
7270
7271         // don't let sound skip if going slow
7272         if (r_refdef.scene.extraupdate)
7273                 S_ExtraUpdate ();
7274
7275         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7276         {
7277                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7278                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7279                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7280                 // don't let sound skip if going slow
7281                 if (r_refdef.scene.extraupdate)
7282                         S_ExtraUpdate ();
7283         }
7284
7285         if (cl.csqc_vidvars.drawworld)
7286         {
7287                 if (cl_decals_newsystem.integer)
7288                 {
7289                         R_DrawModelDecals();
7290                         if (r_timereport_active)
7291                                 R_TimeReport("modeldecals");
7292                 }
7293                 else
7294                 {
7295                         R_DrawDecals();
7296                         if (r_timereport_active)
7297                                 R_TimeReport("decals");
7298                 }
7299
7300                 R_DrawParticles();
7301                 if (r_timereport_active)
7302                         R_TimeReport("particles");
7303
7304                 R_DrawExplosions();
7305                 if (r_timereport_active)
7306                         R_TimeReport("explosions");
7307
7308                 R_DrawLightningBeams();
7309                 if (r_timereport_active)
7310                         R_TimeReport("lightning");
7311         }
7312
7313         if (cl.csqc_loaded)
7314                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7315
7316         if (r_refdef.view.showdebug)
7317         {
7318                 if (cl_locs_show.integer)
7319                 {
7320                         R_DrawLocs();
7321                         if (r_timereport_active)
7322                                 R_TimeReport("showlocs");
7323                 }
7324
7325                 if (r_drawportals.integer)
7326                 {
7327                         R_DrawPortals();
7328                         if (r_timereport_active)
7329                                 R_TimeReport("portals");
7330                 }
7331
7332                 if (r_showbboxes.value > 0)
7333                 {
7334                         R_DrawEntityBBoxes();
7335                         if (r_timereport_active)
7336                                 R_TimeReport("bboxes");
7337                 }
7338         }
7339
7340         if (r_transparent.integer)
7341         {
7342                 R_MeshQueue_RenderTransparent();
7343                 if (r_timereport_active)
7344                         R_TimeReport("drawtrans");
7345         }
7346
7347         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))
7348         {
7349                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7350                 if (r_timereport_active)
7351                         R_TimeReport("worlddebug");
7352                 R_DrawModelsDebug();
7353                 if (r_timereport_active)
7354                         R_TimeReport("modeldebug");
7355         }
7356
7357         if (cl.csqc_vidvars.drawworld)
7358         {
7359                 R_Shadow_DrawCoronas();
7360                 if (r_timereport_active)
7361                         R_TimeReport("coronas");
7362         }
7363
7364 #if 0
7365         {
7366                 GL_DepthTest(false);
7367                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7368                 GL_Color(1, 1, 1, 1);
7369                 qglBegin(GL_POLYGON);
7370                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7371                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7372                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7373                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7374                 qglEnd();
7375                 qglBegin(GL_POLYGON);
7376                 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]);
7377                 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]);
7378                 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]);
7379                 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]);
7380                 qglEnd();
7381                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7382         }
7383 #endif
7384
7385         // don't let sound skip if going slow
7386         if (r_refdef.scene.extraupdate)
7387                 S_ExtraUpdate ();
7388 }
7389
7390 static const unsigned short bboxelements[36] =
7391 {
7392         5, 1, 3, 5, 3, 7,
7393         6, 2, 0, 6, 0, 4,
7394         7, 3, 2, 7, 2, 6,
7395         4, 0, 1, 4, 1, 5,
7396         4, 5, 7, 4, 7, 6,
7397         1, 0, 2, 1, 2, 3,
7398 };
7399
7400 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7401 {
7402         int i;
7403         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7404
7405         RSurf_ActiveWorldEntity();
7406
7407         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7408         GL_DepthMask(false);
7409         GL_DepthRange(0, 1);
7410         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7411 //      R_Mesh_ResetTextureState();
7412
7413         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7414         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7415         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7416         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7417         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7418         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7419         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7420         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7421         R_FillColors(color4f, 8, cr, cg, cb, ca);
7422         if (r_refdef.fogenabled)
7423         {
7424                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7425                 {
7426                         f1 = RSurf_FogVertex(v);
7427                         f2 = 1 - f1;
7428                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7429                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7430                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7431                 }
7432         }
7433         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7434         R_Mesh_ResetTextureState();
7435         R_SetupShader_Generic_NoTexture(false, false);
7436         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7437 }
7438
7439 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7440 {
7441         prvm_prog_t *prog = SVVM_prog;
7442         int i;
7443         float color[4];
7444         prvm_edict_t *edict;
7445
7446         // this function draws bounding boxes of server entities
7447         if (!sv.active)
7448                 return;
7449
7450         GL_CullFace(GL_NONE);
7451         R_SetupShader_Generic_NoTexture(false, false);
7452
7453         for (i = 0;i < numsurfaces;i++)
7454         {
7455                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7456                 switch ((int)PRVM_serveredictfloat(edict, solid))
7457                 {
7458                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7459                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7460                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7461                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7462                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7463                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7464                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7465                 }
7466                 color[3] *= r_showbboxes.value;
7467                 color[3] = bound(0, color[3], 1);
7468                 GL_DepthTest(!r_showdisabledepthtest.integer);
7469                 GL_CullFace(r_refdef.view.cullface_front);
7470                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7471         }
7472 }
7473
7474 static void R_DrawEntityBBoxes(void)
7475 {
7476         int i;
7477         prvm_edict_t *edict;
7478         vec3_t center;
7479         prvm_prog_t *prog = SVVM_prog;
7480
7481         // this function draws bounding boxes of server entities
7482         if (!sv.active)
7483                 return;
7484
7485         for (i = 0;i < prog->num_edicts;i++)
7486         {
7487                 edict = PRVM_EDICT_NUM(i);
7488                 if (edict->priv.server->free)
7489                         continue;
7490                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7491                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7492                         continue;
7493                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7494                         continue;
7495                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7496                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7497         }
7498 }
7499
7500 static const int nomodelelement3i[24] =
7501 {
7502         5, 2, 0,
7503         5, 1, 2,
7504         5, 0, 3,
7505         5, 3, 1,
7506         0, 2, 4,
7507         2, 1, 4,
7508         3, 0, 4,
7509         1, 3, 4
7510 };
7511
7512 static const unsigned short nomodelelement3s[24] =
7513 {
7514         5, 2, 0,
7515         5, 1, 2,
7516         5, 0, 3,
7517         5, 3, 1,
7518         0, 2, 4,
7519         2, 1, 4,
7520         3, 0, 4,
7521         1, 3, 4
7522 };
7523
7524 static const float nomodelvertex3f[6*3] =
7525 {
7526         -16,   0,   0,
7527          16,   0,   0,
7528           0, -16,   0,
7529           0,  16,   0,
7530           0,   0, -16,
7531           0,   0,  16
7532 };
7533
7534 static const float nomodelcolor4f[6*4] =
7535 {
7536         0.0f, 0.0f, 0.5f, 1.0f,
7537         0.0f, 0.0f, 0.5f, 1.0f,
7538         0.0f, 0.5f, 0.0f, 1.0f,
7539         0.0f, 0.5f, 0.0f, 1.0f,
7540         0.5f, 0.0f, 0.0f, 1.0f,
7541         0.5f, 0.0f, 0.0f, 1.0f
7542 };
7543
7544 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7545 {
7546         int i;
7547         float f1, f2, *c;
7548         float color4f[6*4];
7549
7550         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);
7551
7552         // this is only called once per entity so numsurfaces is always 1, and
7553         // surfacelist is always {0}, so this code does not handle batches
7554
7555         if (rsurface.ent_flags & RENDER_ADDITIVE)
7556         {
7557                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7558                 GL_DepthMask(false);
7559         }
7560         else if (rsurface.colormod[3] < 1)
7561         {
7562                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7563                 GL_DepthMask(false);
7564         }
7565         else
7566         {
7567                 GL_BlendFunc(GL_ONE, GL_ZERO);
7568                 GL_DepthMask(true);
7569         }
7570         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7571         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7572         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7573         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7574         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7575         for (i = 0, c = color4f;i < 6;i++, c += 4)
7576         {
7577                 c[0] *= rsurface.colormod[0];
7578                 c[1] *= rsurface.colormod[1];
7579                 c[2] *= rsurface.colormod[2];
7580                 c[3] *= rsurface.colormod[3];
7581         }
7582         if (r_refdef.fogenabled)
7583         {
7584                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7585                 {
7586                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7587                         f2 = 1 - f1;
7588                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7589                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7590                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7591                 }
7592         }
7593 //      R_Mesh_ResetTextureState();
7594         R_SetupShader_Generic_NoTexture(false, false);
7595         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7596         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7597 }
7598
7599 void R_DrawNoModel(entity_render_t *ent)
7600 {
7601         vec3_t org;
7602         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7603         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7604                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7605         else
7606                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7607 }
7608
7609 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7610 {
7611         vec3_t right1, right2, diff, normal;
7612
7613         VectorSubtract (org2, org1, normal);
7614
7615         // calculate 'right' vector for start
7616         VectorSubtract (r_refdef.view.origin, org1, diff);
7617         CrossProduct (normal, diff, right1);
7618         VectorNormalize (right1);
7619
7620         // calculate 'right' vector for end
7621         VectorSubtract (r_refdef.view.origin, org2, diff);
7622         CrossProduct (normal, diff, right2);
7623         VectorNormalize (right2);
7624
7625         vert[ 0] = org1[0] + width * right1[0];
7626         vert[ 1] = org1[1] + width * right1[1];
7627         vert[ 2] = org1[2] + width * right1[2];
7628         vert[ 3] = org1[0] - width * right1[0];
7629         vert[ 4] = org1[1] - width * right1[1];
7630         vert[ 5] = org1[2] - width * right1[2];
7631         vert[ 6] = org2[0] - width * right2[0];
7632         vert[ 7] = org2[1] - width * right2[1];
7633         vert[ 8] = org2[2] - width * right2[2];
7634         vert[ 9] = org2[0] + width * right2[0];
7635         vert[10] = org2[1] + width * right2[1];
7636         vert[11] = org2[2] + width * right2[2];
7637 }
7638
7639 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)
7640 {
7641         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7642         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7643         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7644         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7645         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7646         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7647         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7648         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7649         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7650         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7651         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7652         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7653 }
7654
7655 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7656 {
7657         int i;
7658         float *vertex3f;
7659         float v[3];
7660         VectorSet(v, x, y, z);
7661         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7662                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7663                         break;
7664         if (i == mesh->numvertices)
7665         {
7666                 if (mesh->numvertices < mesh->maxvertices)
7667                 {
7668                         VectorCopy(v, vertex3f);
7669                         mesh->numvertices++;
7670                 }
7671                 return mesh->numvertices;
7672         }
7673         else
7674                 return i;
7675 }
7676
7677 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7678 {
7679         int i;
7680         int *e, element[3];
7681         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7682         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7683         e = mesh->element3i + mesh->numtriangles * 3;
7684         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7685         {
7686                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7687                 if (mesh->numtriangles < mesh->maxtriangles)
7688                 {
7689                         *e++ = element[0];
7690                         *e++ = element[1];
7691                         *e++ = element[2];
7692                         mesh->numtriangles++;
7693                 }
7694                 element[1] = element[2];
7695         }
7696 }
7697
7698 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7699 {
7700         int i;
7701         int *e, element[3];
7702         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7703         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7704         e = mesh->element3i + mesh->numtriangles * 3;
7705         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7706         {
7707                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7708                 if (mesh->numtriangles < mesh->maxtriangles)
7709                 {
7710                         *e++ = element[0];
7711                         *e++ = element[1];
7712                         *e++ = element[2];
7713                         mesh->numtriangles++;
7714                 }
7715                 element[1] = element[2];
7716         }
7717 }
7718
7719 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7720 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7721 {
7722         int planenum, planenum2;
7723         int w;
7724         int tempnumpoints;
7725         mplane_t *plane, *plane2;
7726         double maxdist;
7727         double temppoints[2][256*3];
7728         // figure out how large a bounding box we need to properly compute this brush
7729         maxdist = 0;
7730         for (w = 0;w < numplanes;w++)
7731                 maxdist = max(maxdist, fabs(planes[w].dist));
7732         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7733         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7734         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7735         {
7736                 w = 0;
7737                 tempnumpoints = 4;
7738                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7739                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7740                 {
7741                         if (planenum2 == planenum)
7742                                 continue;
7743                         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);
7744                         w = !w;
7745                 }
7746                 if (tempnumpoints < 3)
7747                         continue;
7748                 // generate elements forming a triangle fan for this polygon
7749                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7750         }
7751 }
7752
7753 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)
7754 {
7755         texturelayer_t *layer;
7756         layer = t->currentlayers + t->currentnumlayers++;
7757         layer->type = type;
7758         layer->depthmask = depthmask;
7759         layer->blendfunc1 = blendfunc1;
7760         layer->blendfunc2 = blendfunc2;
7761         layer->texture = texture;
7762         layer->texmatrix = *matrix;
7763         layer->color[0] = r;
7764         layer->color[1] = g;
7765         layer->color[2] = b;
7766         layer->color[3] = a;
7767 }
7768
7769 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7770 {
7771         if(parms[0] == 0 && parms[1] == 0)
7772                 return false;
7773         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7774                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7775                         return false;
7776         return true;
7777 }
7778
7779 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7780 {
7781         double index, f;
7782         index = parms[2] + rsurface.shadertime * parms[3];
7783         index -= floor(index);
7784         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7785         {
7786         default:
7787         case Q3WAVEFUNC_NONE:
7788         case Q3WAVEFUNC_NOISE:
7789         case Q3WAVEFUNC_COUNT:
7790                 f = 0;
7791                 break;
7792         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7793         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7794         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7795         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7796         case Q3WAVEFUNC_TRIANGLE:
7797                 index *= 4;
7798                 f = index - floor(index);
7799                 if (index < 1)
7800                 {
7801                         // f = f;
7802                 }
7803                 else if (index < 2)
7804                         f = 1 - f;
7805                 else if (index < 3)
7806                         f = -f;
7807                 else
7808                         f = -(1 - f);
7809                 break;
7810         }
7811         f = parms[0] + parms[1] * f;
7812         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7813                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7814         return (float) f;
7815 }
7816
7817 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7818 {
7819         int w, h, idx;
7820         double f;
7821         double offsetd[2];
7822         float tcmat[12];
7823         matrix4x4_t matrix, temp;
7824         switch(tcmod->tcmod)
7825         {
7826                 case Q3TCMOD_COUNT:
7827                 case Q3TCMOD_NONE:
7828                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7829                                 matrix = r_waterscrollmatrix;
7830                         else
7831                                 matrix = identitymatrix;
7832                         break;
7833                 case Q3TCMOD_ENTITYTRANSLATE:
7834                         // this is used in Q3 to allow the gamecode to control texcoord
7835                         // scrolling on the entity, which is not supported in darkplaces yet.
7836                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7837                         break;
7838                 case Q3TCMOD_ROTATE:
7839                         f = tcmod->parms[0] * rsurface.shadertime;
7840                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7841                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7842                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7843                         break;
7844                 case Q3TCMOD_SCALE:
7845                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7846                         break;
7847                 case Q3TCMOD_SCROLL:
7848                         // extra care is needed because of precision breakdown with large values of time
7849                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7850                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7851                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7852                         break;
7853                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7854                         w = (int) tcmod->parms[0];
7855                         h = (int) tcmod->parms[1];
7856                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7857                         f = f - floor(f);
7858                         idx = (int) floor(f * w * h);
7859                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7860                         break;
7861                 case Q3TCMOD_STRETCH:
7862                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7863                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7864                         break;
7865                 case Q3TCMOD_TRANSFORM:
7866                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7867                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7868                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7869                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7870                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7871                         break;
7872                 case Q3TCMOD_TURBULENT:
7873                         // this is handled in the RSurf_PrepareVertices function
7874                         matrix = identitymatrix;
7875                         break;
7876         }
7877         temp = *texmatrix;
7878         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7879 }
7880
7881 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7882 {
7883         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7884         char name[MAX_QPATH];
7885         skinframe_t *skinframe;
7886         unsigned char pixels[296*194];
7887         strlcpy(cache->name, skinname, sizeof(cache->name));
7888         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7889         if (developer_loading.integer)
7890                 Con_Printf("loading %s\n", name);
7891         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7892         if (!skinframe || !skinframe->base)
7893         {
7894                 unsigned char *f;
7895                 fs_offset_t filesize;
7896                 skinframe = NULL;
7897                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7898                 if (f)
7899                 {
7900                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7901                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7902                         Mem_Free(f);
7903                 }
7904         }
7905         cache->skinframe = skinframe;
7906 }
7907
7908 texture_t *R_GetCurrentTexture(texture_t *t)
7909 {
7910         int i;
7911         const entity_render_t *ent = rsurface.entity;
7912         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7913         q3shaderinfo_layer_tcmod_t *tcmod;
7914
7915         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7916                 return t->currentframe;
7917         t->update_lastrenderframe = r_textureframe;
7918         t->update_lastrenderentity = (void *)ent;
7919
7920         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7921                 t->camera_entity = ent->entitynumber;
7922         else
7923                 t->camera_entity = 0;
7924
7925         // switch to an alternate material if this is a q1bsp animated material
7926         {
7927                 texture_t *texture = t;
7928                 int s = rsurface.ent_skinnum;
7929                 if ((unsigned int)s >= (unsigned int)model->numskins)
7930                         s = 0;
7931                 if (model->skinscenes)
7932                 {
7933                         if (model->skinscenes[s].framecount > 1)
7934                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7935                         else
7936                                 s = model->skinscenes[s].firstframe;
7937                 }
7938                 if (s > 0)
7939                         t = t + s * model->num_surfaces;
7940                 if (t->animated)
7941                 {
7942                         // use an alternate animation if the entity's frame is not 0,
7943                         // and only if the texture has an alternate animation
7944                         if (rsurface.ent_alttextures && t->anim_total[1])
7945                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7946                         else
7947                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7948                 }
7949                 texture->currentframe = t;
7950         }
7951
7952         // update currentskinframe to be a qw skin or animation frame
7953         if (rsurface.ent_qwskin >= 0)
7954         {
7955                 i = rsurface.ent_qwskin;
7956                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7957                 {
7958                         r_qwskincache_size = cl.maxclients;
7959                         if (r_qwskincache)
7960                                 Mem_Free(r_qwskincache);
7961                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7962                 }
7963                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7964                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7965                 t->currentskinframe = r_qwskincache[i].skinframe;
7966                 if (t->currentskinframe == NULL)
7967                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7968         }
7969         else if (t->numskinframes >= 2)
7970                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7971         if (t->backgroundnumskinframes >= 2)
7972                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7973
7974         t->currentmaterialflags = t->basematerialflags;
7975         t->currentalpha = rsurface.colormod[3];
7976         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7977                 t->currentalpha *= r_wateralpha.value;
7978         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7979                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7980         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7981                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7982         if (!(rsurface.ent_flags & RENDER_LIGHT))
7983                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7984         else if (FAKELIGHT_ENABLED)
7985         {
7986                 // no modellight if using fakelight for the map
7987         }
7988         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7989         {
7990                 // pick a model lighting mode
7991                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7992                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7993                 else
7994                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7995         }
7996         if (rsurface.ent_flags & RENDER_ADDITIVE)
7997                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7998         else if (t->currentalpha < 1)
7999                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
8000         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
8001         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8002                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
8003         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
8004                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
8005         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
8006                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
8007         if (t->backgroundnumskinframes)
8008                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
8009         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
8010         {
8011                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
8012                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
8013         }
8014         else
8015                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
8016         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
8017         {
8018                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
8019                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
8020         }
8021         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
8022                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
8023
8024         // there is no tcmod
8025         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
8026         {
8027                 t->currenttexmatrix = r_waterscrollmatrix;
8028                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
8029         }
8030         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
8031         {
8032                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
8033                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
8034         }
8035
8036         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8037                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
8038         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
8039                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
8040
8041         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
8042         if (t->currentskinframe->qpixels)
8043                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
8044         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
8045         if (!t->basetexture)
8046                 t->basetexture = r_texture_notexture;
8047         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
8048         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
8049         t->nmaptexture = t->currentskinframe->nmap;
8050         if (!t->nmaptexture)
8051                 t->nmaptexture = r_texture_blanknormalmap;
8052         t->glosstexture = r_texture_black;
8053         t->glowtexture = t->currentskinframe->glow;
8054         t->fogtexture = t->currentskinframe->fog;
8055         t->reflectmasktexture = t->currentskinframe->reflect;
8056         if (t->backgroundnumskinframes)
8057         {
8058                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
8059                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
8060                 t->backgroundglosstexture = r_texture_black;
8061                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
8062                 if (!t->backgroundnmaptexture)
8063                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8064                 // make sure that if glow is going to be used, both textures are not NULL
8065                 if (!t->backgroundglowtexture && t->glowtexture)
8066                         t->backgroundglowtexture = r_texture_black;
8067                 if (!t->glowtexture && t->backgroundglowtexture)
8068                         t->glowtexture = r_texture_black;
8069         }
8070         else
8071         {
8072                 t->backgroundbasetexture = r_texture_white;
8073                 t->backgroundnmaptexture = r_texture_blanknormalmap;
8074                 t->backgroundglosstexture = r_texture_black;
8075                 t->backgroundglowtexture = NULL;
8076         }
8077         t->specularpower = r_shadow_glossexponent.value;
8078         // TODO: store reference values for these in the texture?
8079         t->specularscale = 0;
8080         if (r_shadow_gloss.integer > 0)
8081         {
8082                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
8083                 {
8084                         if (r_shadow_glossintensity.value > 0)
8085                         {
8086                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
8087                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
8088                                 t->specularscale = r_shadow_glossintensity.value;
8089                         }
8090                 }
8091                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
8092                 {
8093                         t->glosstexture = r_texture_white;
8094                         t->backgroundglosstexture = r_texture_white;
8095                         t->specularscale = r_shadow_gloss2intensity.value;
8096                         t->specularpower = r_shadow_gloss2exponent.value;
8097                 }
8098         }
8099         t->specularscale *= t->specularscalemod;
8100         t->specularpower *= t->specularpowermod;
8101         t->rtlightambient = 0;
8102
8103         // lightmaps mode looks bad with dlights using actual texturing, so turn
8104         // off the colormap and glossmap, but leave the normalmap on as it still
8105         // accurately represents the shading involved
8106         if (gl_lightmaps.integer)
8107         {
8108                 t->basetexture = r_texture_grey128;
8109                 t->pantstexture = r_texture_black;
8110                 t->shirttexture = r_texture_black;
8111                 if (gl_lightmaps.integer < 2)
8112                         t->nmaptexture = r_texture_blanknormalmap;
8113                 t->glosstexture = r_texture_black;
8114                 t->glowtexture = NULL;
8115                 t->fogtexture = NULL;
8116                 t->reflectmasktexture = NULL;
8117                 t->backgroundbasetexture = NULL;
8118                 if (gl_lightmaps.integer < 2)
8119                         t->backgroundnmaptexture = r_texture_blanknormalmap;
8120                 t->backgroundglosstexture = r_texture_black;
8121                 t->backgroundglowtexture = NULL;
8122                 t->specularscale = 0;
8123                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
8124         }
8125
8126         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
8127         VectorClear(t->dlightcolor);
8128         t->currentnumlayers = 0;
8129         if (t->currentmaterialflags & MATERIALFLAG_WALL)
8130         {
8131                 int blendfunc1, blendfunc2;
8132                 qboolean depthmask;
8133                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
8134                 {
8135                         blendfunc1 = GL_SRC_ALPHA;
8136                         blendfunc2 = GL_ONE;
8137                 }
8138                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8139                 {
8140                         blendfunc1 = GL_SRC_ALPHA;
8141                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8142                 }
8143                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8144                 {
8145                         blendfunc1 = t->customblendfunc[0];
8146                         blendfunc2 = t->customblendfunc[1];
8147                 }
8148                 else
8149                 {
8150                         blendfunc1 = GL_ONE;
8151                         blendfunc2 = GL_ZERO;
8152                 }
8153                 // don't colormod evilblend textures
8154                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8155                         VectorSet(t->lightmapcolor, 1, 1, 1);
8156                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8157                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8158                 {
8159                         // fullbright is not affected by r_refdef.lightmapintensity
8160                         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]);
8161                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8162                                 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]);
8163                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8164                                 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]);
8165                 }
8166                 else
8167                 {
8168                         vec3_t ambientcolor;
8169                         float colorscale;
8170                         // set the color tint used for lights affecting this surface
8171                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8172                         colorscale = 2;
8173                         // q3bsp has no lightmap updates, so the lightstylevalue that
8174                         // would normally be baked into the lightmap must be
8175                         // applied to the color
8176                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8177                         if (model->type == mod_brushq3)
8178                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8179                         colorscale *= r_refdef.lightmapintensity;
8180                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8181                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8182                         // basic lit geometry
8183                         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]);
8184                         // add pants/shirt if needed
8185                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8186                                 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]);
8187                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8188                                 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]);
8189                         // now add ambient passes if needed
8190                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8191                         {
8192                                 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]);
8193                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8194                                         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]);
8195                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8196                                         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]);
8197                         }
8198                 }
8199                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8200                         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]);
8201                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8202                 {
8203                         // if this is opaque use alpha blend which will darken the earlier
8204                         // passes cheaply.
8205                         //
8206                         // if this is an alpha blended material, all the earlier passes
8207                         // were darkened by fog already, so we only need to add the fog
8208                         // color ontop through the fog mask texture
8209                         //
8210                         // if this is an additive blended material, all the earlier passes
8211                         // were darkened by fog already, and we should not add fog color
8212                         // (because the background was not darkened, there is no fog color
8213                         // that was lost behind it).
8214                         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]);
8215                 }
8216         }
8217
8218         return t->currentframe;
8219 }
8220
8221 rsurfacestate_t rsurface;
8222
8223 void RSurf_ActiveWorldEntity(void)
8224 {
8225         dp_model_t *model = r_refdef.scene.worldmodel;
8226         //if (rsurface.entity == r_refdef.scene.worldentity)
8227         //      return;
8228         rsurface.entity = r_refdef.scene.worldentity;
8229         rsurface.skeleton = NULL;
8230         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8231         rsurface.ent_skinnum = 0;
8232         rsurface.ent_qwskin = -1;
8233         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8234         rsurface.shadertime = r_refdef.scene.time;
8235         rsurface.matrix = identitymatrix;
8236         rsurface.inversematrix = identitymatrix;
8237         rsurface.matrixscale = 1;
8238         rsurface.inversematrixscale = 1;
8239         R_EntityMatrix(&identitymatrix);
8240         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8241         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8242         rsurface.fograngerecip = r_refdef.fograngerecip;
8243         rsurface.fogheightfade = r_refdef.fogheightfade;
8244         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8245         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8246         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8247         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8248         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8249         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8250         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8251         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8252         rsurface.colormod[3] = 1;
8253         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);
8254         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8255         rsurface.frameblend[0].lerp = 1;
8256         rsurface.ent_alttextures = false;
8257         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8258         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8259         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8260         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8261         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8262         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8263         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8264         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8265         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8266         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8267         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8268         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8269         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8270         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8271         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8272         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8273         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8274         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8275         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8276         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8277         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8278         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8279         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8280         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8281         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8282         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8283         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8284         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8285         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8286         rsurface.modelelement3i = model->surfmesh.data_element3i;
8287         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8288         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8289         rsurface.modelelement3s = model->surfmesh.data_element3s;
8290         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8291         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8292         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8293         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8294         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8295         rsurface.modelsurfaces = model->data_surfaces;
8296         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8297         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8298         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8299         rsurface.modelgeneratedvertex = false;
8300         rsurface.batchgeneratedvertex = false;
8301         rsurface.batchfirstvertex = 0;
8302         rsurface.batchnumvertices = 0;
8303         rsurface.batchfirsttriangle = 0;
8304         rsurface.batchnumtriangles = 0;
8305         rsurface.batchvertex3f  = NULL;
8306         rsurface.batchvertex3f_vertexbuffer = NULL;
8307         rsurface.batchvertex3f_bufferoffset = 0;
8308         rsurface.batchsvector3f = NULL;
8309         rsurface.batchsvector3f_vertexbuffer = NULL;
8310         rsurface.batchsvector3f_bufferoffset = 0;
8311         rsurface.batchtvector3f = NULL;
8312         rsurface.batchtvector3f_vertexbuffer = NULL;
8313         rsurface.batchtvector3f_bufferoffset = 0;
8314         rsurface.batchnormal3f  = NULL;
8315         rsurface.batchnormal3f_vertexbuffer = NULL;
8316         rsurface.batchnormal3f_bufferoffset = 0;
8317         rsurface.batchlightmapcolor4f = NULL;
8318         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8319         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8320         rsurface.batchtexcoordtexture2f = NULL;
8321         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8322         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8323         rsurface.batchtexcoordlightmap2f = NULL;
8324         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8325         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8326         rsurface.batchskeletalindex4ub = NULL;
8327         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8328         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8329         rsurface.batchskeletalweight4ub = NULL;
8330         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8331         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8332         rsurface.batchvertexmesh = NULL;
8333         rsurface.batchvertexmeshbuffer = NULL;
8334         rsurface.batchvertex3fbuffer = NULL;
8335         rsurface.batchelement3i = NULL;
8336         rsurface.batchelement3i_indexbuffer = NULL;
8337         rsurface.batchelement3i_bufferoffset = 0;
8338         rsurface.batchelement3s = NULL;
8339         rsurface.batchelement3s_indexbuffer = NULL;
8340         rsurface.batchelement3s_bufferoffset = 0;
8341         rsurface.passcolor4f = NULL;
8342         rsurface.passcolor4f_vertexbuffer = NULL;
8343         rsurface.passcolor4f_bufferoffset = 0;
8344         rsurface.forcecurrenttextureupdate = false;
8345 }
8346
8347 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8348 {
8349         dp_model_t *model = ent->model;
8350         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8351         //      return;
8352         rsurface.entity = (entity_render_t *)ent;
8353         rsurface.skeleton = ent->skeleton;
8354         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8355         rsurface.ent_skinnum = ent->skinnum;
8356         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;
8357         rsurface.ent_flags = ent->flags;
8358         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8359         rsurface.matrix = ent->matrix;
8360         rsurface.inversematrix = ent->inversematrix;
8361         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8362         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8363         R_EntityMatrix(&rsurface.matrix);
8364         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8365         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8366         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8367         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8368         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8369         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8370         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8371         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8372         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8373         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8374         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8375         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8376         rsurface.colormod[3] = ent->alpha;
8377         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8378         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8379         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8380         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8381         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8382         if (ent->model->brush.submodel && !prepass)
8383         {
8384                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8385                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8386         }
8387         // if the animcache code decided it should use the shader path, skip the deform step
8388         rsurface.entityskeletaltransform3x4 = ent->animcache_vertex3f ? NULL : ent->animcache_skeletaltransform3x4;
8389         rsurface.entityskeletalnumtransforms = rsurface.entityskeletaltransform3x4 ? model->num_bones : 0;
8390         if (model->surfmesh.isanimated && model->AnimateVertices && !rsurface.entityskeletaltransform3x4)
8391         {
8392                 if (ent->animcache_vertex3f)
8393                 {
8394                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8395                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8396                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8397                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8398                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8399                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8400                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8401                 }
8402                 else if (wanttangents)
8403                 {
8404                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8405                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8406                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8407                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8408                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8409                         rsurface.modelvertexmesh = NULL;
8410                         rsurface.modelvertexmeshbuffer = NULL;
8411                         rsurface.modelvertex3fbuffer = NULL;
8412                 }
8413                 else if (wantnormals)
8414                 {
8415                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8416                         rsurface.modelsvector3f = NULL;
8417                         rsurface.modeltvector3f = NULL;
8418                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8419                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8420                         rsurface.modelvertexmesh = NULL;
8421                         rsurface.modelvertexmeshbuffer = NULL;
8422                         rsurface.modelvertex3fbuffer = NULL;
8423                 }
8424                 else
8425                 {
8426                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8427                         rsurface.modelsvector3f = NULL;
8428                         rsurface.modeltvector3f = NULL;
8429                         rsurface.modelnormal3f = NULL;
8430                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8431                         rsurface.modelvertexmesh = NULL;
8432                         rsurface.modelvertexmeshbuffer = NULL;
8433                         rsurface.modelvertex3fbuffer = NULL;
8434                 }
8435                 rsurface.modelvertex3f_vertexbuffer = 0;
8436                 rsurface.modelvertex3f_bufferoffset = 0;
8437                 rsurface.modelsvector3f_vertexbuffer = 0;
8438                 rsurface.modelsvector3f_bufferoffset = 0;
8439                 rsurface.modeltvector3f_vertexbuffer = 0;
8440                 rsurface.modeltvector3f_bufferoffset = 0;
8441                 rsurface.modelnormal3f_vertexbuffer = 0;
8442                 rsurface.modelnormal3f_bufferoffset = 0;
8443                 rsurface.modelgeneratedvertex = true;
8444         }
8445         else
8446         {
8447                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8448                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8449                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8450                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8451                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8452                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8453                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8454                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8455                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8456                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8457                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8458                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8459                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8460                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8461                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8462                 rsurface.modelgeneratedvertex = false;
8463         }
8464         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8465         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8466         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8467         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8468         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8469         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8470         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8471         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8472         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8473         rsurface.modelskeletalindex4ub = model->surfmesh.data_skeletalindex4ub;
8474         rsurface.modelskeletalindex4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8475         rsurface.modelskeletalindex4ub_bufferoffset = model->surfmesh.vbooffset_skeletalindex4ub;
8476         rsurface.modelskeletalweight4ub = model->surfmesh.data_skeletalweight4ub;
8477         rsurface.modelskeletalweight4ub_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8478         rsurface.modelskeletalweight4ub_bufferoffset = model->surfmesh.vbooffset_skeletalweight4ub;
8479         rsurface.modelelement3i = model->surfmesh.data_element3i;
8480         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8481         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8482         rsurface.modelelement3s = model->surfmesh.data_element3s;
8483         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8484         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8485         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8486         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8487         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8488         rsurface.modelsurfaces = model->data_surfaces;
8489         rsurface.batchgeneratedvertex = false;
8490         rsurface.batchfirstvertex = 0;
8491         rsurface.batchnumvertices = 0;
8492         rsurface.batchfirsttriangle = 0;
8493         rsurface.batchnumtriangles = 0;
8494         rsurface.batchvertex3f  = NULL;
8495         rsurface.batchvertex3f_vertexbuffer = NULL;
8496         rsurface.batchvertex3f_bufferoffset = 0;
8497         rsurface.batchsvector3f = NULL;
8498         rsurface.batchsvector3f_vertexbuffer = NULL;
8499         rsurface.batchsvector3f_bufferoffset = 0;
8500         rsurface.batchtvector3f = NULL;
8501         rsurface.batchtvector3f_vertexbuffer = NULL;
8502         rsurface.batchtvector3f_bufferoffset = 0;
8503         rsurface.batchnormal3f  = NULL;
8504         rsurface.batchnormal3f_vertexbuffer = NULL;
8505         rsurface.batchnormal3f_bufferoffset = 0;
8506         rsurface.batchlightmapcolor4f = NULL;
8507         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8508         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8509         rsurface.batchtexcoordtexture2f = NULL;
8510         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8511         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8512         rsurface.batchtexcoordlightmap2f = NULL;
8513         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8514         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8515         rsurface.batchskeletalindex4ub = NULL;
8516         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8517         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8518         rsurface.batchskeletalweight4ub = NULL;
8519         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8520         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8521         rsurface.batchvertexmesh = NULL;
8522         rsurface.batchvertexmeshbuffer = NULL;
8523         rsurface.batchvertex3fbuffer = NULL;
8524         rsurface.batchelement3i = NULL;
8525         rsurface.batchelement3i_indexbuffer = NULL;
8526         rsurface.batchelement3i_bufferoffset = 0;
8527         rsurface.batchelement3s = NULL;
8528         rsurface.batchelement3s_indexbuffer = NULL;
8529         rsurface.batchelement3s_bufferoffset = 0;
8530         rsurface.passcolor4f = NULL;
8531         rsurface.passcolor4f_vertexbuffer = NULL;
8532         rsurface.passcolor4f_bufferoffset = 0;
8533         rsurface.forcecurrenttextureupdate = false;
8534 }
8535
8536 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)
8537 {
8538         rsurface.entity = r_refdef.scene.worldentity;
8539         rsurface.skeleton = NULL;
8540         rsurface.ent_skinnum = 0;
8541         rsurface.ent_qwskin = -1;
8542         rsurface.ent_flags = entflags;
8543         rsurface.shadertime = r_refdef.scene.time - shadertime;
8544         rsurface.modelnumvertices = numvertices;
8545         rsurface.modelnumtriangles = numtriangles;
8546         rsurface.matrix = *matrix;
8547         rsurface.inversematrix = *inversematrix;
8548         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8549         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8550         R_EntityMatrix(&rsurface.matrix);
8551         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8552         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8553         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8554         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8555         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8556         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8557         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8558         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8559         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8560         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8561         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8562         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8563         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);
8564         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8565         rsurface.frameblend[0].lerp = 1;
8566         rsurface.ent_alttextures = false;
8567         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8568         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8569         if (wanttangents)
8570         {
8571                 rsurface.modelvertex3f = (float *)vertex3f;
8572                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8573                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8574                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8575         }
8576         else if (wantnormals)
8577         {
8578                 rsurface.modelvertex3f = (float *)vertex3f;
8579                 rsurface.modelsvector3f = NULL;
8580                 rsurface.modeltvector3f = NULL;
8581                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8582         }
8583         else
8584         {
8585                 rsurface.modelvertex3f = (float *)vertex3f;
8586                 rsurface.modelsvector3f = NULL;
8587                 rsurface.modeltvector3f = NULL;
8588                 rsurface.modelnormal3f = NULL;
8589         }
8590         rsurface.modelvertexmesh = NULL;
8591         rsurface.modelvertexmeshbuffer = NULL;
8592         rsurface.modelvertex3fbuffer = NULL;
8593         rsurface.modelvertex3f_vertexbuffer = 0;
8594         rsurface.modelvertex3f_bufferoffset = 0;
8595         rsurface.modelsvector3f_vertexbuffer = 0;
8596         rsurface.modelsvector3f_bufferoffset = 0;
8597         rsurface.modeltvector3f_vertexbuffer = 0;
8598         rsurface.modeltvector3f_bufferoffset = 0;
8599         rsurface.modelnormal3f_vertexbuffer = 0;
8600         rsurface.modelnormal3f_bufferoffset = 0;
8601         rsurface.modelgeneratedvertex = true;
8602         rsurface.modellightmapcolor4f  = (float *)color4f;
8603         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8604         rsurface.modellightmapcolor4f_bufferoffset = 0;
8605         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8606         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8607         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8608         rsurface.modeltexcoordlightmap2f  = NULL;
8609         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8610         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8611         rsurface.modelskeletalindex4ub = NULL;
8612         rsurface.modelskeletalindex4ub_vertexbuffer = NULL;
8613         rsurface.modelskeletalindex4ub_bufferoffset = 0;
8614         rsurface.modelskeletalweight4ub = NULL;
8615         rsurface.modelskeletalweight4ub_vertexbuffer = NULL;
8616         rsurface.modelskeletalweight4ub_bufferoffset = 0;
8617         rsurface.modelelement3i = (int *)element3i;
8618         rsurface.modelelement3i_indexbuffer = NULL;
8619         rsurface.modelelement3i_bufferoffset = 0;
8620         rsurface.modelelement3s = (unsigned short *)element3s;
8621         rsurface.modelelement3s_indexbuffer = NULL;
8622         rsurface.modelelement3s_bufferoffset = 0;
8623         rsurface.modellightmapoffsets = NULL;
8624         rsurface.modelsurfaces = NULL;
8625         rsurface.batchgeneratedvertex = false;
8626         rsurface.batchfirstvertex = 0;
8627         rsurface.batchnumvertices = 0;
8628         rsurface.batchfirsttriangle = 0;
8629         rsurface.batchnumtriangles = 0;
8630         rsurface.batchvertex3f  = NULL;
8631         rsurface.batchvertex3f_vertexbuffer = NULL;
8632         rsurface.batchvertex3f_bufferoffset = 0;
8633         rsurface.batchsvector3f = NULL;
8634         rsurface.batchsvector3f_vertexbuffer = NULL;
8635         rsurface.batchsvector3f_bufferoffset = 0;
8636         rsurface.batchtvector3f = NULL;
8637         rsurface.batchtvector3f_vertexbuffer = NULL;
8638         rsurface.batchtvector3f_bufferoffset = 0;
8639         rsurface.batchnormal3f  = NULL;
8640         rsurface.batchnormal3f_vertexbuffer = NULL;
8641         rsurface.batchnormal3f_bufferoffset = 0;
8642         rsurface.batchlightmapcolor4f = NULL;
8643         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8644         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8645         rsurface.batchtexcoordtexture2f = NULL;
8646         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8647         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8648         rsurface.batchtexcoordlightmap2f = NULL;
8649         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8650         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8651         rsurface.batchskeletalindex4ub = NULL;
8652         rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
8653         rsurface.batchskeletalindex4ub_bufferoffset = 0;
8654         rsurface.batchskeletalweight4ub = NULL;
8655         rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
8656         rsurface.batchskeletalweight4ub_bufferoffset = 0;
8657         rsurface.batchvertexmesh = NULL;
8658         rsurface.batchvertexmeshbuffer = NULL;
8659         rsurface.batchvertex3fbuffer = NULL;
8660         rsurface.batchelement3i = NULL;
8661         rsurface.batchelement3i_indexbuffer = NULL;
8662         rsurface.batchelement3i_bufferoffset = 0;
8663         rsurface.batchelement3s = NULL;
8664         rsurface.batchelement3s_indexbuffer = NULL;
8665         rsurface.batchelement3s_bufferoffset = 0;
8666         rsurface.passcolor4f = NULL;
8667         rsurface.passcolor4f_vertexbuffer = NULL;
8668         rsurface.passcolor4f_bufferoffset = 0;
8669         rsurface.forcecurrenttextureupdate = true;
8670
8671         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8672         {
8673                 if ((wantnormals || wanttangents) && !normal3f)
8674                 {
8675                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8676                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8677                 }
8678                 if (wanttangents && !svector3f)
8679                 {
8680                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8681                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8682                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8683                 }
8684         }
8685 }
8686
8687 float RSurf_FogPoint(const float *v)
8688 {
8689         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8690         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8691         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8692         float FogHeightFade = r_refdef.fogheightfade;
8693         float fogfrac;
8694         unsigned int fogmasktableindex;
8695         if (r_refdef.fogplaneviewabove)
8696                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8697         else
8698                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8699         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8700         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8701 }
8702
8703 float RSurf_FogVertex(const float *v)
8704 {
8705         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8706         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8707         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8708         float FogHeightFade = rsurface.fogheightfade;
8709         float fogfrac;
8710         unsigned int fogmasktableindex;
8711         if (r_refdef.fogplaneviewabove)
8712                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8713         else
8714                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8715         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8716         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8717 }
8718
8719 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8720 {
8721         int i;
8722         for (i = 0;i < numelements;i++)
8723                 outelement3i[i] = inelement3i[i] + adjust;
8724 }
8725
8726 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8727 extern cvar_t gl_vbo;
8728 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8729 {
8730         int deformindex;
8731         int firsttriangle;
8732         int numtriangles;
8733         int firstvertex;
8734         int endvertex;
8735         int numvertices;
8736         int surfacefirsttriangle;
8737         int surfacenumtriangles;
8738         int surfacefirstvertex;
8739         int surfaceendvertex;
8740         int surfacenumvertices;
8741         int batchnumvertices;
8742         int batchnumtriangles;
8743         int needsupdate;
8744         int i, j;
8745         qboolean gaps;
8746         qboolean dynamicvertex;
8747         float amplitude;
8748         float animpos;
8749         float scale;
8750         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8751         float waveparms[4];
8752         unsigned char *ub;
8753         q3shaderinfo_deform_t *deform;
8754         const msurface_t *surface, *firstsurface;
8755         r_vertexmesh_t *vertexmesh;
8756         if (!texturenumsurfaces)
8757                 return;
8758         // find vertex range of this surface batch
8759         gaps = false;
8760         firstsurface = texturesurfacelist[0];
8761         firsttriangle = firstsurface->num_firsttriangle;
8762         batchnumvertices = 0;
8763         batchnumtriangles = 0;
8764         firstvertex = endvertex = firstsurface->num_firstvertex;
8765         for (i = 0;i < texturenumsurfaces;i++)
8766         {
8767                 surface = texturesurfacelist[i];
8768                 if (surface != firstsurface + i)
8769                         gaps = true;
8770                 surfacefirstvertex = surface->num_firstvertex;
8771                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8772                 surfacenumvertices = surface->num_vertices;
8773                 surfacenumtriangles = surface->num_triangles;
8774                 if (firstvertex > surfacefirstvertex)
8775                         firstvertex = surfacefirstvertex;
8776                 if (endvertex < surfaceendvertex)
8777                         endvertex = surfaceendvertex;
8778                 batchnumvertices += surfacenumvertices;
8779                 batchnumtriangles += surfacenumtriangles;
8780         }
8781
8782         // we now know the vertex range used, and if there are any gaps in it
8783         rsurface.batchfirstvertex = firstvertex;
8784         rsurface.batchnumvertices = endvertex - firstvertex;
8785         rsurface.batchfirsttriangle = firsttriangle;
8786         rsurface.batchnumtriangles = batchnumtriangles;
8787
8788         // this variable holds flags for which properties have been updated that
8789         // may require regenerating vertexmesh array...
8790         needsupdate = 0;
8791
8792         // check if any dynamic vertex processing must occur
8793         dynamicvertex = false;
8794
8795         // if there is a chance of animated vertex colors, it's a dynamic batch
8796         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8797         {
8798                 dynamicvertex = true;
8799                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8800         }
8801
8802         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8803         {
8804                 switch (deform->deform)
8805                 {
8806                 default:
8807                 case Q3DEFORM_PROJECTIONSHADOW:
8808                 case Q3DEFORM_TEXT0:
8809                 case Q3DEFORM_TEXT1:
8810                 case Q3DEFORM_TEXT2:
8811                 case Q3DEFORM_TEXT3:
8812                 case Q3DEFORM_TEXT4:
8813                 case Q3DEFORM_TEXT5:
8814                 case Q3DEFORM_TEXT6:
8815                 case Q3DEFORM_TEXT7:
8816                 case Q3DEFORM_NONE:
8817                         break;
8818                 case Q3DEFORM_AUTOSPRITE:
8819                         dynamicvertex = true;
8820                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD;
8821                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8822                         break;
8823                 case Q3DEFORM_AUTOSPRITE2:
8824                         dynamicvertex = true;
8825                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8826                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8827                         break;
8828                 case Q3DEFORM_NORMAL:
8829                         dynamicvertex = true;
8830                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8831                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8832                         break;
8833                 case Q3DEFORM_WAVE:
8834                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8835                                 break; // if wavefunc is a nop, ignore this transform
8836                         dynamicvertex = true;
8837                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8838                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8839                         break;
8840                 case Q3DEFORM_BULGE:
8841                         dynamicvertex = true;
8842                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD;
8843                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8844                         break;
8845                 case Q3DEFORM_MOVE:
8846                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8847                                 break; // if wavefunc is a nop, ignore this transform
8848                         dynamicvertex = true;
8849                         batchneed |= BATCHNEED_ARRAY_VERTEX;
8850                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8851                         break;
8852                 }
8853         }
8854         switch(rsurface.texture->tcgen.tcgen)
8855         {
8856         default:
8857         case Q3TCGEN_TEXTURE:
8858                 break;
8859         case Q3TCGEN_LIGHTMAP:
8860                 dynamicvertex = true;
8861                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8862                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8863                 break;
8864         case Q3TCGEN_VECTOR:
8865                 dynamicvertex = true;
8866                 batchneed |= BATCHNEED_ARRAY_VERTEX;
8867                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8868                 break;
8869         case Q3TCGEN_ENVIRONMENT:
8870                 dynamicvertex = true;
8871                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL;
8872                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8873                 break;
8874         }
8875         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8876         {
8877                 dynamicvertex = true;
8878                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD;
8879                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8880         }
8881
8882         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8883         {
8884                 dynamicvertex = true;
8885                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8886         }
8887
8888         // when the model data has no vertex buffer (dynamic mesh), we need to
8889         // eliminate gaps
8890         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8891                 batchneed |= BATCHNEED_NOGAPS;
8892
8893         // the caller can specify BATCHNEED_NOGAPS to force a batch with
8894         // firstvertex = 0 and endvertex = numvertices (no gaps, no firstvertex),
8895         // we ensure this by treating the vertex batch as dynamic...
8896         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex > 0))
8897                 dynamicvertex = true;
8898
8899         if (dynamicvertex)
8900         {
8901                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8902                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8903                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8904                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8905                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8906                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8907                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8908                 if (batchneed & BATCHNEED_VERTEXMESH_SKELETAL)    batchneed |= BATCHNEED_ARRAY_SKELETAL;
8909         }
8910
8911         // if needsupdate, we have to do a dynamic vertex batch for sure
8912         if (needsupdate & batchneed)
8913                 dynamicvertex = true;
8914
8915         // see if we need to build vertexmesh from arrays
8916         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8917                 dynamicvertex = true;
8918
8919         rsurface.batchvertex3f = rsurface.modelvertex3f;
8920         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8921         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8922         rsurface.batchsvector3f = rsurface.modelsvector3f;
8923         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8924         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8925         rsurface.batchtvector3f = rsurface.modeltvector3f;
8926         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8927         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8928         rsurface.batchnormal3f = rsurface.modelnormal3f;
8929         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8930         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8931         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8932         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8933         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8934         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8935         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8936         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8937         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8938         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8939         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8940         rsurface.batchskeletalindex4ub = rsurface.modelskeletalindex4ub;
8941         rsurface.batchskeletalindex4ub_vertexbuffer = rsurface.modelskeletalindex4ub_vertexbuffer;
8942         rsurface.batchskeletalindex4ub_bufferoffset = rsurface.modelskeletalindex4ub_bufferoffset;
8943         rsurface.batchskeletalweight4ub = rsurface.modelskeletalweight4ub;
8944         rsurface.batchskeletalweight4ub_vertexbuffer = rsurface.modelskeletalweight4ub_vertexbuffer;
8945         rsurface.batchskeletalweight4ub_bufferoffset = rsurface.modelskeletalweight4ub_bufferoffset;
8946         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8947         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8948         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8949         rsurface.batchelement3i = rsurface.modelelement3i;
8950         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8951         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8952         rsurface.batchelement3s = rsurface.modelelement3s;
8953         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8954         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8955
8956         // if any dynamic vertex processing has to occur in software, we copy the
8957         // entire surface list together before processing to rebase the vertices
8958         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8959         //
8960         // if any gaps exist and we do not have a static vertex buffer, we have to
8961         // copy the surface list together to avoid wasting upload bandwidth on the
8962         // vertices in the gaps.
8963         //
8964         // if gaps exist and we have a static vertex buffer, we can choose whether
8965         // to combine the index buffer ranges into one dynamic index buffer or
8966         // simply issue multiple glDrawElements calls (BATCHNEED_ALLOWMULTIDRAW).
8967         //
8968         // in many cases the batch is reduced to one draw call.
8969
8970         rsurface.batchmultidraw = false;
8971         rsurface.batchmultidrawnumsurfaces = 0;
8972         rsurface.batchmultidrawsurfacelist = NULL;
8973
8974         if (!dynamicvertex)
8975         {
8976                 // static vertex data, just set pointers...
8977                 rsurface.batchgeneratedvertex = false;
8978                 // if there are gaps, we want to build a combined index buffer,
8979                 // otherwise use the original static buffer with an appropriate offset
8980                 if (gaps)
8981                 {
8982                         if ((batchneed & BATCHNEED_ALLOWMULTIDRAW) && r_batch_multidraw.integer && batchnumtriangles >= r_batch_multidraw_mintriangles.integer)
8983                         {
8984                                 rsurface.batchmultidraw = true;
8985                                 rsurface.batchmultidrawnumsurfaces = texturenumsurfaces;
8986                                 rsurface.batchmultidrawsurfacelist = texturesurfacelist;
8987                                 return;
8988                         }
8989                         // build a new triangle elements array for this batch
8990                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8991                         rsurface.batchfirsttriangle = 0;
8992                         numtriangles = 0;
8993                         for (i = 0;i < texturenumsurfaces;i++)
8994                         {
8995                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8996                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8997                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8998                                 numtriangles += surfacenumtriangles;
8999                         }
9000                         rsurface.batchelement3i_indexbuffer = NULL;
9001                         rsurface.batchelement3i_bufferoffset = 0;
9002                         rsurface.batchelement3s = NULL;
9003                         rsurface.batchelement3s_indexbuffer = NULL;
9004                         rsurface.batchelement3s_bufferoffset = 0;
9005                         if (endvertex <= 65536)
9006                         {
9007                                 // make a 16bit (unsigned short) index array if possible
9008                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9009                                 for (i = 0;i < numtriangles*3;i++)
9010                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9011                         }
9012                 }
9013                 return;
9014         }
9015
9016         // something needs software processing, do it for real...
9017         // we only directly handle separate array data in this case and then
9018         // generate interleaved data if needed...
9019         rsurface.batchgeneratedvertex = true;
9020
9021         // now copy the vertex data into a combined array and make an index array
9022         // (this is what Quake3 does all the time)
9023         //if (dynamicvertex)
9024         {
9025                 rsurface.batchvertex3fbuffer = NULL;
9026                 rsurface.batchvertexmesh = NULL;
9027                 rsurface.batchvertexmeshbuffer = NULL;
9028                 rsurface.batchvertex3f = NULL;
9029                 rsurface.batchvertex3f_vertexbuffer = NULL;
9030                 rsurface.batchvertex3f_bufferoffset = 0;
9031                 rsurface.batchsvector3f = NULL;
9032                 rsurface.batchsvector3f_vertexbuffer = NULL;
9033                 rsurface.batchsvector3f_bufferoffset = 0;
9034                 rsurface.batchtvector3f = NULL;
9035                 rsurface.batchtvector3f_vertexbuffer = NULL;
9036                 rsurface.batchtvector3f_bufferoffset = 0;
9037                 rsurface.batchnormal3f = NULL;
9038                 rsurface.batchnormal3f_vertexbuffer = NULL;
9039                 rsurface.batchnormal3f_bufferoffset = 0;
9040                 rsurface.batchlightmapcolor4f = NULL;
9041                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9042                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9043                 rsurface.batchtexcoordtexture2f = NULL;
9044                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9045                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9046                 rsurface.batchtexcoordlightmap2f = NULL;
9047                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
9048                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
9049                 rsurface.batchskeletalindex4ub = NULL;
9050                 rsurface.batchskeletalindex4ub_vertexbuffer = NULL;
9051                 rsurface.batchskeletalindex4ub_bufferoffset = 0;
9052                 rsurface.batchskeletalweight4ub = NULL;
9053                 rsurface.batchskeletalweight4ub_vertexbuffer = NULL;
9054                 rsurface.batchskeletalweight4ub_bufferoffset = 0;
9055                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
9056                 rsurface.batchelement3i_indexbuffer = NULL;
9057                 rsurface.batchelement3i_bufferoffset = 0;
9058                 rsurface.batchelement3s = NULL;
9059                 rsurface.batchelement3s_indexbuffer = NULL;
9060                 rsurface.batchelement3s_bufferoffset = 0;
9061                 // we'll only be setting up certain arrays as needed
9062                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9063                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9064                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9065                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9066                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9067                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9068                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9069                 {
9070                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9071                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9072                 }
9073                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9074                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9075                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9076                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9077                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9078                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9079                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9080                 {
9081                         rsurface.batchskeletalindex4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9082                         rsurface.batchskeletalweight4ub = (unsigned char *)R_FrameData_Alloc(batchnumvertices * sizeof(unsigned char[4]));
9083                 }
9084                 numvertices = 0;
9085                 numtriangles = 0;
9086                 for (i = 0;i < texturenumsurfaces;i++)
9087                 {
9088                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
9089                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
9090                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
9091                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
9092                         // copy only the data requested
9093                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
9094                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
9095                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
9096                         {
9097                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
9098                                 {
9099                                         if (rsurface.batchvertex3f)
9100                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9101                                         else
9102                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9103                                 }
9104                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
9105                                 {
9106                                         if (rsurface.modelnormal3f)
9107                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9108                                         else
9109                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9110                                 }
9111                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
9112                                 {
9113                                         if (rsurface.modelsvector3f)
9114                                         {
9115                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9116                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
9117                                         }
9118                                         else
9119                                         {
9120                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9121                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
9122                                         }
9123                                 }
9124                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
9125                                 {
9126                                         if (rsurface.modellightmapcolor4f)
9127                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
9128                                         else
9129                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
9130                                 }
9131                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
9132                                 {
9133                                         if (rsurface.modeltexcoordtexture2f)
9134                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9135                                         else
9136                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9137                                 }
9138                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
9139                                 {
9140                                         if (rsurface.modeltexcoordlightmap2f)
9141                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
9142                                         else
9143                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
9144                                 }
9145                                 if (batchneed & BATCHNEED_ARRAY_SKELETAL)
9146                                 {
9147                                         if (rsurface.modelskeletalindex4ub)
9148                                         {
9149                                                 memcpy(rsurface.batchskeletalindex4ub + 4*numvertices, rsurface.modelskeletalindex4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9150                                                 memcpy(rsurface.batchskeletalweight4ub + 4*numvertices, rsurface.modelskeletalweight4ub + 4*surfacefirstvertex, surfacenumvertices * sizeof(unsigned char[4]));
9151                                         }
9152                                         else
9153                                         {
9154                                                 memset(rsurface.batchskeletalindex4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9155                                                 memset(rsurface.batchskeletalweight4ub + 4*numvertices, 0, surfacenumvertices * sizeof(unsigned char[4]));
9156                                                 ub = rsurface.batchskeletalweight4ub + 4*numvertices;
9157                                                 for (j = 0;j < surfacenumvertices;j++)
9158                                                         ub[j*4] = 255;
9159                                         }
9160                                 }
9161                         }
9162                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
9163                         numvertices += surfacenumvertices;
9164                         numtriangles += surfacenumtriangles;
9165                 }
9166
9167                 // generate a 16bit index array as well if possible
9168                 // (in general, dynamic batches fit)
9169                 if (numvertices <= 65536)
9170                 {
9171                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
9172                         for (i = 0;i < numtriangles*3;i++)
9173                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
9174                 }
9175
9176                 // since we've copied everything, the batch now starts at 0
9177                 rsurface.batchfirstvertex = 0;
9178                 rsurface.batchnumvertices = batchnumvertices;
9179                 rsurface.batchfirsttriangle = 0;
9180                 rsurface.batchnumtriangles = batchnumtriangles;
9181         }
9182
9183         // q1bsp surfaces rendered in vertex color mode have to have colors
9184         // calculated based on lightstyles
9185         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
9186         {
9187                 // generate color arrays for the surfaces in this list
9188                 int c[4];
9189                 int scale;
9190                 int size3;
9191                 const int *offsets;
9192                 const unsigned char *lm;
9193                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
9194                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
9195                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
9196                 numvertices = 0;
9197                 for (i = 0;i < texturenumsurfaces;i++)
9198                 {
9199                         surface = texturesurfacelist[i];
9200                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
9201                         surfacenumvertices = surface->num_vertices;
9202                         if (surface->lightmapinfo->samples)
9203                         {
9204                                 for (j = 0;j < surfacenumvertices;j++)
9205                                 {
9206                                         lm = surface->lightmapinfo->samples + offsets[j];
9207                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
9208                                         VectorScale(lm, scale, c);
9209                                         if (surface->lightmapinfo->styles[1] != 255)
9210                                         {
9211                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
9212                                                 lm += size3;
9213                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
9214                                                 VectorMA(c, scale, lm, c);
9215                                                 if (surface->lightmapinfo->styles[2] != 255)
9216                                                 {
9217                                                         lm += size3;
9218                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
9219                                                         VectorMA(c, scale, lm, c);
9220                                                         if (surface->lightmapinfo->styles[3] != 255)
9221                                                         {
9222                                                                 lm += size3;
9223                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9224                                                                 VectorMA(c, scale, lm, c);
9225                                                         }
9226                                                 }
9227                                         }
9228                                         c[0] >>= 7;
9229                                         c[1] >>= 7;
9230                                         c[2] >>= 7;
9231                                         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);
9232                                         numvertices++;
9233                                 }
9234                         }
9235                         else
9236                         {
9237                                 for (j = 0;j < surfacenumvertices;j++)
9238                                 {
9239                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9240                                         numvertices++;
9241                                 }
9242                         }
9243                 }
9244         }
9245
9246         // if vertices are deformed (sprite flares and things in maps, possibly
9247         // water waves, bulges and other deformations), modify the copied vertices
9248         // in place
9249         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9250         {
9251                 switch (deform->deform)
9252                 {
9253                 default:
9254                 case Q3DEFORM_PROJECTIONSHADOW:
9255                 case Q3DEFORM_TEXT0:
9256                 case Q3DEFORM_TEXT1:
9257                 case Q3DEFORM_TEXT2:
9258                 case Q3DEFORM_TEXT3:
9259                 case Q3DEFORM_TEXT4:
9260                 case Q3DEFORM_TEXT5:
9261                 case Q3DEFORM_TEXT6:
9262                 case Q3DEFORM_TEXT7:
9263                 case Q3DEFORM_NONE:
9264                         break;
9265                 case Q3DEFORM_AUTOSPRITE:
9266                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9267                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9268                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9269                         VectorNormalize(newforward);
9270                         VectorNormalize(newright);
9271                         VectorNormalize(newup);
9272 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9273 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9274 //                      rsurface.batchvertex3f_bufferoffset = 0;
9275 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9276 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9277 //                      rsurface.batchsvector3f_bufferoffset = 0;
9278 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9279 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9280 //                      rsurface.batchtvector3f_bufferoffset = 0;
9281 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9282 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9283 //                      rsurface.batchnormal3f_bufferoffset = 0;
9284                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9285                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9286                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9287                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9288                                 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);
9289                         // a single autosprite surface can contain multiple sprites...
9290                         for (j = 0;j < batchnumvertices - 3;j += 4)
9291                         {
9292                                 VectorClear(center);
9293                                 for (i = 0;i < 4;i++)
9294                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9295                                 VectorScale(center, 0.25f, center);
9296                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9297                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9298                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9299                                 for (i = 0;i < 4;i++)
9300                                 {
9301                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9302                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9303                                 }
9304                         }
9305                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9306                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9307                         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);
9308                         break;
9309                 case Q3DEFORM_AUTOSPRITE2:
9310                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9311                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9312                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9313                         VectorNormalize(newforward);
9314                         VectorNormalize(newright);
9315                         VectorNormalize(newup);
9316 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9317 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9318 //                      rsurface.batchvertex3f_bufferoffset = 0;
9319                         {
9320                                 const float *v1, *v2;
9321                                 vec3_t start, end;
9322                                 float f, l;
9323                                 struct
9324                                 {
9325                                         float length2;
9326                                         const float *v1;
9327                                         const float *v2;
9328                                 }
9329                                 shortest[2];
9330                                 memset(shortest, 0, sizeof(shortest));
9331                                 // a single autosprite surface can contain multiple sprites...
9332                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9333                                 {
9334                                         VectorClear(center);
9335                                         for (i = 0;i < 4;i++)
9336                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9337                                         VectorScale(center, 0.25f, center);
9338                                         // find the two shortest edges, then use them to define the
9339                                         // axis vectors for rotating around the central axis
9340                                         for (i = 0;i < 6;i++)
9341                                         {
9342                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9343                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9344                                                 l = VectorDistance2(v1, v2);
9345                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9346                                                 if (v1[2] != v2[2])
9347                                                         l += (1.0f / 1024.0f);
9348                                                 if (shortest[0].length2 > l || i == 0)
9349                                                 {
9350                                                         shortest[1] = shortest[0];
9351                                                         shortest[0].length2 = l;
9352                                                         shortest[0].v1 = v1;
9353                                                         shortest[0].v2 = v2;
9354                                                 }
9355                                                 else if (shortest[1].length2 > l || i == 1)
9356                                                 {
9357                                                         shortest[1].length2 = l;
9358                                                         shortest[1].v1 = v1;
9359                                                         shortest[1].v2 = v2;
9360                                                 }
9361                                         }
9362                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9363                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9364                                         // this calculates the right vector from the shortest edge
9365                                         // and the up vector from the edge midpoints
9366                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9367                                         VectorNormalize(right);
9368                                         VectorSubtract(end, start, up);
9369                                         VectorNormalize(up);
9370                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9371                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9372                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9373                                         VectorNegate(forward, forward);
9374                                         VectorReflect(forward, 0, up, forward);
9375                                         VectorNormalize(forward);
9376                                         CrossProduct(up, forward, newright);
9377                                         VectorNormalize(newright);
9378                                         // rotate the quad around the up axis vector, this is made
9379                                         // especially easy by the fact we know the quad is flat,
9380                                         // so we only have to subtract the center position and
9381                                         // measure distance along the right vector, and then
9382                                         // multiply that by the newright vector and add back the
9383                                         // center position
9384                                         // we also need to subtract the old position to undo the
9385                                         // displacement from the center, which we do with a
9386                                         // DotProduct, the subtraction/addition of center is also
9387                                         // optimized into DotProducts here
9388                                         l = DotProduct(right, center);
9389                                         for (i = 0;i < 4;i++)
9390                                         {
9391                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9392                                                 f = DotProduct(right, v1) - l;
9393                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9394                                         }
9395                                 }
9396                         }
9397                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9398                         {
9399 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9400 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9401 //                              rsurface.batchnormal3f_bufferoffset = 0;
9402                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9403                         }
9404                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9405                         {
9406 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9407 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9408 //                              rsurface.batchsvector3f_bufferoffset = 0;
9409 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9410 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9411 //                              rsurface.batchtvector3f_bufferoffset = 0;
9412                                 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);
9413                         }
9414                         break;
9415                 case Q3DEFORM_NORMAL:
9416                         // deform the normals to make reflections wavey
9417                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9418                         rsurface.batchnormal3f_vertexbuffer = NULL;
9419                         rsurface.batchnormal3f_bufferoffset = 0;
9420                         for (j = 0;j < batchnumvertices;j++)
9421                         {
9422                                 float vertex[3];
9423                                 float *normal = rsurface.batchnormal3f + 3*j;
9424                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9425                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9426                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9427                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9428                                 VectorNormalize(normal);
9429                         }
9430                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9431                         {
9432 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9433 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9434 //                              rsurface.batchsvector3f_bufferoffset = 0;
9435 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9436 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9437 //                              rsurface.batchtvector3f_bufferoffset = 0;
9438                                 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);
9439                         }
9440                         break;
9441                 case Q3DEFORM_WAVE:
9442                         // deform vertex array to make wavey water and flags and such
9443                         waveparms[0] = deform->waveparms[0];
9444                         waveparms[1] = deform->waveparms[1];
9445                         waveparms[2] = deform->waveparms[2];
9446                         waveparms[3] = deform->waveparms[3];
9447                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9448                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9449                         // this is how a divisor of vertex influence on deformation
9450                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9451                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9452 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9453 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9454 //                      rsurface.batchvertex3f_bufferoffset = 0;
9455 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9456 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9457 //                      rsurface.batchnormal3f_bufferoffset = 0;
9458                         for (j = 0;j < batchnumvertices;j++)
9459                         {
9460                                 // if the wavefunc depends on time, evaluate it per-vertex
9461                                 if (waveparms[3])
9462                                 {
9463                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9464                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9465                                 }
9466                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9467                         }
9468                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9469                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9470                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9471                         {
9472 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9473 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9474 //                              rsurface.batchsvector3f_bufferoffset = 0;
9475 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9476 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9477 //                              rsurface.batchtvector3f_bufferoffset = 0;
9478                                 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);
9479                         }
9480                         break;
9481                 case Q3DEFORM_BULGE:
9482                         // deform vertex array to make the surface have moving bulges
9483 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9484 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9485 //                      rsurface.batchvertex3f_bufferoffset = 0;
9486 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9487 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9488 //                      rsurface.batchnormal3f_bufferoffset = 0;
9489                         for (j = 0;j < batchnumvertices;j++)
9490                         {
9491                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9492                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9493                         }
9494                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9495                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9496                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9497                         {
9498 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9499 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9500 //                              rsurface.batchsvector3f_bufferoffset = 0;
9501 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9502 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9503 //                              rsurface.batchtvector3f_bufferoffset = 0;
9504                                 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);
9505                         }
9506                         break;
9507                 case Q3DEFORM_MOVE:
9508                         // deform vertex array
9509                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9510                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9511                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9512                         VectorScale(deform->parms, scale, waveparms);
9513 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9514 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9515 //                      rsurface.batchvertex3f_bufferoffset = 0;
9516                         for (j = 0;j < batchnumvertices;j++)
9517                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9518                         break;
9519                 }
9520         }
9521
9522         // generate texcoords based on the chosen texcoord source
9523         switch(rsurface.texture->tcgen.tcgen)
9524         {
9525         default:
9526         case Q3TCGEN_TEXTURE:
9527                 break;
9528         case Q3TCGEN_LIGHTMAP:
9529 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9530 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9531 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9532                 if (rsurface.batchtexcoordlightmap2f)
9533                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9534                 break;
9535         case Q3TCGEN_VECTOR:
9536 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9537 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9538 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9539                 for (j = 0;j < batchnumvertices;j++)
9540                 {
9541                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9542                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9543                 }
9544                 break;
9545         case Q3TCGEN_ENVIRONMENT:
9546                 // make environment reflections using a spheremap
9547                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9548                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9549                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9550                 for (j = 0;j < batchnumvertices;j++)
9551                 {
9552                         // identical to Q3A's method, but executed in worldspace so
9553                         // carried models can be shiny too
9554
9555                         float viewer[3], d, reflected[3], worldreflected[3];
9556
9557                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9558                         // VectorNormalize(viewer);
9559
9560                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9561
9562                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9563                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9564                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9565                         // note: this is proportinal to viewer, so we can normalize later
9566
9567                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9568                         VectorNormalize(worldreflected);
9569
9570                         // note: this sphere map only uses world x and z!
9571                         // so positive and negative y will LOOK THE SAME.
9572                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9573                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9574                 }
9575                 break;
9576         }
9577         // the only tcmod that needs software vertex processing is turbulent, so
9578         // check for it here and apply the changes if needed
9579         // and we only support that as the first one
9580         // (handling a mixture of turbulent and other tcmods would be problematic
9581         //  without punting it entirely to a software path)
9582         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9583         {
9584                 amplitude = rsurface.texture->tcmods[0].parms[1];
9585                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9586 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9587 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9588 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9589                 for (j = 0;j < batchnumvertices;j++)
9590                 {
9591                         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);
9592                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9593                 }
9594         }
9595
9596         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9597         {
9598                 // convert the modified arrays to vertex structs
9599 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9600 //              rsurface.batchvertexmeshbuffer = NULL;
9601                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9602                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9603                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9604                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9605                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9606                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9607                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9608                 {
9609                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9610                         {
9611                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9612                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9613                         }
9614                 }
9615                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9616                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9617                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9618                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9619                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9620                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9621                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9622                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9623                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9624                 if ((batchneed & BATCHNEED_VERTEXMESH_SKELETAL) && rsurface.batchskeletalindex4ub)
9625                 {
9626                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9627                         {
9628                                 Vector4Copy(rsurface.batchskeletalindex4ub + 4*j, vertexmesh->skeletalindex4ub);
9629                                 Vector4Copy(rsurface.batchskeletalweight4ub + 4*j, vertexmesh->skeletalweight4ub);
9630                         }
9631                 }
9632         }
9633 }
9634
9635 void RSurf_DrawBatch(void)
9636 {
9637         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9638         // through the pipeline, killing it earlier in the pipeline would have
9639         // per-surface overhead rather than per-batch overhead, so it's best to
9640         // reject it here, before it hits glDraw.
9641         if (rsurface.batchnumtriangles == 0)
9642                 return;
9643 #if 0
9644         // batch debugging code
9645         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9646         {
9647                 int i;
9648                 int j;
9649                 int c;
9650                 const int *e;
9651                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9652                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9653                 {
9654                         c = e[i];
9655                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9656                         {
9657                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9658                                 {
9659                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9660                                                 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);
9661                                         break;
9662                                 }
9663                         }
9664                 }
9665         }
9666 #endif
9667         if (rsurface.batchmultidraw)
9668         {
9669                 // issue multiple draws rather than copying index data
9670                 int numsurfaces = rsurface.batchmultidrawnumsurfaces;
9671                 const msurface_t **surfacelist = rsurface.batchmultidrawsurfacelist;
9672                 int i, j, k, firstvertex, endvertex, firsttriangle, endtriangle;
9673                 for (i = 0;i < numsurfaces;)
9674                 {
9675                         // combine consecutive surfaces as one draw
9676                         for (k = i, j = i + 1;j < numsurfaces;k = j, j++)
9677                                 if (surfacelist[j] != surfacelist[k] + 1)
9678                                         break;
9679                         firstvertex = surfacelist[i]->num_firstvertex;
9680                         endvertex = surfacelist[k]->num_firstvertex + surfacelist[k]->num_vertices;
9681                         firsttriangle = surfacelist[i]->num_firsttriangle;
9682                         endtriangle = surfacelist[k]->num_firsttriangle + surfacelist[k]->num_triangles;
9683                         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);
9684                         i = j;
9685                 }
9686         }
9687         else
9688         {
9689                 // there is only one consecutive run of index data (may have been combined)
9690                 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);
9691         }
9692 }
9693
9694 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9695 {
9696         // pick the closest matching water plane
9697         int planeindex, vertexindex, bestplaneindex = -1;
9698         float d, bestd;
9699         vec3_t vert;
9700         const float *v;
9701         r_waterstate_waterplane_t *p;
9702         qboolean prepared = false;
9703         bestd = 0;
9704         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9705         {
9706                 if(p->camera_entity != rsurface.texture->camera_entity)
9707                         continue;
9708                 d = 0;
9709                 if(!prepared)
9710                 {
9711                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, 1, &surface);
9712                         prepared = true;
9713                         if(rsurface.batchnumvertices == 0)
9714                                 break;
9715                 }
9716                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9717                 {
9718                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9719                         d += fabs(PlaneDiff(vert, &p->plane));
9720                 }
9721                 if (bestd > d || bestplaneindex < 0)
9722                 {
9723                         bestd = d;
9724                         bestplaneindex = planeindex;
9725                 }
9726         }
9727         return bestplaneindex;
9728         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9729         // this situation though, as it might be better to render single larger
9730         // batches with useless stuff (backface culled for example) than to
9731         // render multiple smaller batches
9732 }
9733
9734 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9735 {
9736         int i;
9737         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9738         rsurface.passcolor4f_vertexbuffer = 0;
9739         rsurface.passcolor4f_bufferoffset = 0;
9740         for (i = 0;i < rsurface.batchnumvertices;i++)
9741                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9742 }
9743
9744 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9745 {
9746         int i;
9747         float f;
9748         const float *v;
9749         const float *c;
9750         float *c2;
9751         if (rsurface.passcolor4f)
9752         {
9753                 // generate color arrays
9754                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9755                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9756                 rsurface.passcolor4f_vertexbuffer = 0;
9757                 rsurface.passcolor4f_bufferoffset = 0;
9758                 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)
9759                 {
9760                         f = RSurf_FogVertex(v);
9761                         c2[0] = c[0] * f;
9762                         c2[1] = c[1] * f;
9763                         c2[2] = c[2] * f;
9764                         c2[3] = c[3];
9765                 }
9766         }
9767         else
9768         {
9769                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9770                 rsurface.passcolor4f_vertexbuffer = 0;
9771                 rsurface.passcolor4f_bufferoffset = 0;
9772                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9773                 {
9774                         f = RSurf_FogVertex(v);
9775                         c2[0] = f;
9776                         c2[1] = f;
9777                         c2[2] = f;
9778                         c2[3] = 1;
9779                 }
9780         }
9781 }
9782
9783 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9784 {
9785         int i;
9786         float f;
9787         const float *v;
9788         const float *c;
9789         float *c2;
9790         if (!rsurface.passcolor4f)
9791                 return;
9792         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9793         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9794         rsurface.passcolor4f_vertexbuffer = 0;
9795         rsurface.passcolor4f_bufferoffset = 0;
9796         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)
9797         {
9798                 f = RSurf_FogVertex(v);
9799                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9800                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9801                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9802                 c2[3] = c[3];
9803         }
9804 }
9805
9806 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9807 {
9808         int i;
9809         const float *c;
9810         float *c2;
9811         if (!rsurface.passcolor4f)
9812                 return;
9813         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9814         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9815         rsurface.passcolor4f_vertexbuffer = 0;
9816         rsurface.passcolor4f_bufferoffset = 0;
9817         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9818         {
9819                 c2[0] = c[0] * r;
9820                 c2[1] = c[1] * g;
9821                 c2[2] = c[2] * b;
9822                 c2[3] = c[3] * a;
9823         }
9824 }
9825
9826 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9827 {
9828         int i;
9829         const float *c;
9830         float *c2;
9831         if (!rsurface.passcolor4f)
9832                 return;
9833         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9834         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9835         rsurface.passcolor4f_vertexbuffer = 0;
9836         rsurface.passcolor4f_bufferoffset = 0;
9837         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9838         {
9839                 c2[0] = c[0] + r_refdef.scene.ambient;
9840                 c2[1] = c[1] + r_refdef.scene.ambient;
9841                 c2[2] = c[2] + r_refdef.scene.ambient;
9842                 c2[3] = c[3];
9843         }
9844 }
9845
9846 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9847 {
9848         // TODO: optimize
9849         rsurface.passcolor4f = NULL;
9850         rsurface.passcolor4f_vertexbuffer = 0;
9851         rsurface.passcolor4f_bufferoffset = 0;
9852         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9853         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9854         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9855         GL_Color(r, g, b, a);
9856         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9857         RSurf_DrawBatch();
9858 }
9859
9860 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9861 {
9862         // TODO: optimize applyfog && applycolor case
9863         // just apply fog if necessary, and tint the fog color array if necessary
9864         rsurface.passcolor4f = NULL;
9865         rsurface.passcolor4f_vertexbuffer = 0;
9866         rsurface.passcolor4f_bufferoffset = 0;
9867         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9868         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9869         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9870         GL_Color(r, g, b, a);
9871         RSurf_DrawBatch();
9872 }
9873
9874 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9875 {
9876         // TODO: optimize
9877         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9878         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9879         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9880         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9881         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9882         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9883         GL_Color(r, g, b, a);
9884         RSurf_DrawBatch();
9885 }
9886
9887 static void RSurf_DrawBatch_GL11_ClampColor(void)
9888 {
9889         int i;
9890         const float *c1;
9891         float *c2;
9892         if (!rsurface.passcolor4f)
9893                 return;
9894         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9895         {
9896                 c2[0] = bound(0.0f, c1[0], 1.0f);
9897                 c2[1] = bound(0.0f, c1[1], 1.0f);
9898                 c2[2] = bound(0.0f, c1[2], 1.0f);
9899                 c2[3] = bound(0.0f, c1[3], 1.0f);
9900         }
9901 }
9902
9903 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9904 {
9905         int i;
9906         float f;
9907         const float *v;
9908         const float *n;
9909         float *c;
9910         //vec3_t eyedir;
9911
9912         // fake shading
9913         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9914         rsurface.passcolor4f_vertexbuffer = 0;
9915         rsurface.passcolor4f_bufferoffset = 0;
9916         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)
9917         {
9918                 f = -DotProduct(r_refdef.view.forward, n);
9919                 f = max(0, f);
9920                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9921                 f *= r_refdef.lightmapintensity;
9922                 Vector4Set(c, f, f, f, 1);
9923         }
9924 }
9925
9926 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9927 {
9928         RSurf_DrawBatch_GL11_ApplyFakeLight();
9929         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9930         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9931         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9932         GL_Color(r, g, b, a);
9933         RSurf_DrawBatch();
9934 }
9935
9936 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9937 {
9938         int i;
9939         float f;
9940         float alpha;
9941         const float *v;
9942         const float *n;
9943         float *c;
9944         vec3_t ambientcolor;
9945         vec3_t diffusecolor;
9946         vec3_t lightdir;
9947         // TODO: optimize
9948         // model lighting
9949         VectorCopy(rsurface.modellight_lightdir, lightdir);
9950         f = 0.5f * r_refdef.lightmapintensity;
9951         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9952         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9953         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9954         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9955         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9956         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9957         alpha = *a;
9958         if (VectorLength2(diffusecolor) > 0)
9959         {
9960                 // q3-style directional shading
9961                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9962                 rsurface.passcolor4f_vertexbuffer = 0;
9963                 rsurface.passcolor4f_bufferoffset = 0;
9964                 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)
9965                 {
9966                         if ((f = DotProduct(n, lightdir)) > 0)
9967                                 VectorMA(ambientcolor, f, diffusecolor, c);
9968                         else
9969                                 VectorCopy(ambientcolor, c);
9970                         c[3] = alpha;
9971                 }
9972                 *r = 1;
9973                 *g = 1;
9974                 *b = 1;
9975                 *a = 1;
9976                 *applycolor = false;
9977         }
9978         else
9979         {
9980                 *r = ambientcolor[0];
9981                 *g = ambientcolor[1];
9982                 *b = ambientcolor[2];
9983                 rsurface.passcolor4f = NULL;
9984                 rsurface.passcolor4f_vertexbuffer = 0;
9985                 rsurface.passcolor4f_bufferoffset = 0;
9986         }
9987 }
9988
9989 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9990 {
9991         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9992         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9993         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9994         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9995         GL_Color(r, g, b, a);
9996         RSurf_DrawBatch();
9997 }
9998
9999 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
10000 {
10001         int i;
10002         float f;
10003         const float *v;
10004         float *c;
10005
10006         // fake shading
10007         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
10008         rsurface.passcolor4f_vertexbuffer = 0;
10009         rsurface.passcolor4f_bufferoffset = 0;
10010
10011         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
10012         {
10013                 f = 1 - RSurf_FogVertex(v);
10014                 c[0] = r;
10015                 c[1] = g;
10016                 c[2] = b;
10017                 c[3] = f * a;
10018         }
10019 }
10020
10021 void RSurf_SetupDepthAndCulling(void)
10022 {
10023         // submodels are biased to avoid z-fighting with world surfaces that they
10024         // may be exactly overlapping (avoids z-fighting artifacts on certain
10025         // doors and things in Quake maps)
10026         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
10027         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
10028         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
10029         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
10030 }
10031
10032 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10033 {
10034         // transparent sky would be ridiculous
10035         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10036                 return;
10037         R_SetupShader_Generic_NoTexture(false, false);
10038         skyrenderlater = true;
10039         RSurf_SetupDepthAndCulling();
10040         GL_DepthMask(true);
10041         // LordHavoc: HalfLife maps have freaky skypolys so don't use
10042         // skymasking on them, and Quake3 never did sky masking (unlike
10043         // software Quake and software Quake2), so disable the sky masking
10044         // in Quake3 maps as it causes problems with q3map2 sky tricks,
10045         // and skymasking also looks very bad when noclipping outside the
10046         // level, so don't use it then either.
10047         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
10048         {
10049                 R_Mesh_ResetTextureState();
10050                 if (skyrendermasked)
10051                 {
10052                         R_SetupShader_DepthOrShadow(false, false);
10053                         // depth-only (masking)
10054                         GL_ColorMask(0,0,0,0);
10055                         // just to make sure that braindead drivers don't draw
10056                         // anything despite that colormask...
10057                         GL_BlendFunc(GL_ZERO, GL_ONE);
10058                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10059                         if (rsurface.batchvertex3fbuffer)
10060                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10061                         else
10062                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10063                 }
10064                 else
10065                 {
10066                         R_SetupShader_Generic_NoTexture(false, false);
10067                         // fog sky
10068                         GL_BlendFunc(GL_ONE, GL_ZERO);
10069                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10070                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
10071                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
10072                 }
10073                 RSurf_DrawBatch();
10074                 if (skyrendermasked)
10075                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10076         }
10077         R_Mesh_ResetTextureState();
10078         GL_Color(1, 1, 1, 1);
10079 }
10080
10081 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
10082 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
10083 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10084 {
10085         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
10086                 return;
10087         if (prepass)
10088         {
10089                 // render screenspace normalmap to texture
10090                 GL_DepthMask(true);
10091                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
10092                 RSurf_DrawBatch();
10093                 return;
10094         }
10095
10096         // bind lightmap texture
10097
10098         // water/refraction/reflection/camera surfaces have to be handled specially
10099         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
10100         {
10101                 int start, end, startplaneindex;
10102                 for (start = 0;start < texturenumsurfaces;start = end)
10103                 {
10104                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
10105                         if(startplaneindex < 0)
10106                         {
10107                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
10108                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
10109                                 end = start + 1;
10110                                 continue;
10111                         }
10112                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
10113                                 ;
10114                         // now that we have a batch using the same planeindex, render it
10115                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
10116                         {
10117                                 // render water or distortion background
10118                                 GL_DepthMask(true);
10119                                 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);
10120                                 RSurf_DrawBatch();
10121                                 // blend surface on top
10122                                 GL_DepthMask(false);
10123                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
10124                                 RSurf_DrawBatch();
10125                         }
10126                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
10127                         {
10128                                 // render surface with reflection texture as input
10129                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10130                                 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);
10131                                 RSurf_DrawBatch();
10132                         }
10133                 }
10134                 return;
10135         }
10136
10137         // render surface batch normally
10138         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
10139         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);
10140         RSurf_DrawBatch();
10141 }
10142
10143 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10144 {
10145         // OpenGL 1.3 path - anything not completely ancient
10146         qboolean applycolor;
10147         qboolean applyfog;
10148         int layerindex;
10149         const texturelayer_t *layer;
10150         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);
10151         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10152
10153         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10154         {
10155                 vec4_t layercolor;
10156                 int layertexrgbscale;
10157                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10158                 {
10159                         if (layerindex == 0)
10160                                 GL_AlphaTest(true);
10161                         else
10162                         {
10163                                 GL_AlphaTest(false);
10164                                 GL_DepthFunc(GL_EQUAL);
10165                         }
10166                 }
10167                 GL_DepthMask(layer->depthmask && writedepth);
10168                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10169                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
10170                 {
10171                         layertexrgbscale = 4;
10172                         VectorScale(layer->color, 0.25f, layercolor);
10173                 }
10174                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
10175                 {
10176                         layertexrgbscale = 2;
10177                         VectorScale(layer->color, 0.5f, layercolor);
10178                 }
10179                 else
10180                 {
10181                         layertexrgbscale = 1;
10182                         VectorScale(layer->color, 1.0f, layercolor);
10183                 }
10184                 layercolor[3] = layer->color[3];
10185                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
10186                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10187                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10188                 switch (layer->type)
10189                 {
10190                 case TEXTURELAYERTYPE_LITTEXTURE:
10191                         // single-pass lightmapped texture with 2x rgbscale
10192                         R_Mesh_TexBind(0, r_texture_white);
10193                         R_Mesh_TexMatrix(0, NULL);
10194                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10195                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10196                         R_Mesh_TexBind(1, layer->texture);
10197                         R_Mesh_TexMatrix(1, &layer->texmatrix);
10198                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10199                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10200                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10201                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10202                         else if (FAKELIGHT_ENABLED)
10203                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10204                         else if (rsurface.uselightmaptexture)
10205                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10206                         else
10207                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10208                         break;
10209                 case TEXTURELAYERTYPE_TEXTURE:
10210                         // singletexture unlit texture with transparency support
10211                         R_Mesh_TexBind(0, layer->texture);
10212                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10213                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10214                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10215                         R_Mesh_TexBind(1, 0);
10216                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10217                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
10218                         break;
10219                 case TEXTURELAYERTYPE_FOG:
10220                         // singletexture fogging
10221                         if (layer->texture)
10222                         {
10223                                 R_Mesh_TexBind(0, layer->texture);
10224                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10225                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
10226                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10227                         }
10228                         else
10229                         {
10230                                 R_Mesh_TexBind(0, 0);
10231                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10232                         }
10233                         R_Mesh_TexBind(1, 0);
10234                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10235                         // generate a color array for the fog pass
10236                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
10237                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10238                         RSurf_DrawBatch();
10239                         break;
10240                 default:
10241                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10242                 }
10243         }
10244         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10245         {
10246                 GL_DepthFunc(GL_LEQUAL);
10247                 GL_AlphaTest(false);
10248         }
10249 }
10250
10251 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10252 {
10253         // OpenGL 1.1 - crusty old voodoo path
10254         qboolean applyfog;
10255         int layerindex;
10256         const texturelayer_t *layer;
10257         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);
10258         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10259
10260         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10261         {
10262                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10263                 {
10264                         if (layerindex == 0)
10265                                 GL_AlphaTest(true);
10266                         else
10267                         {
10268                                 GL_AlphaTest(false);
10269                                 GL_DepthFunc(GL_EQUAL);
10270                         }
10271                 }
10272                 GL_DepthMask(layer->depthmask && writedepth);
10273                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10274                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10275                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10276                 switch (layer->type)
10277                 {
10278                 case TEXTURELAYERTYPE_LITTEXTURE:
10279                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10280                         {
10281                                 // two-pass lit texture with 2x rgbscale
10282                                 // first the lightmap pass
10283                                 R_Mesh_TexBind(0, r_texture_white);
10284                                 R_Mesh_TexMatrix(0, NULL);
10285                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10286                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10287                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10288                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10289                                 else if (FAKELIGHT_ENABLED)
10290                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10291                                 else if (rsurface.uselightmaptexture)
10292                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10293                                 else
10294                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10295                                 // then apply the texture to it
10296                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10297                                 R_Mesh_TexBind(0, layer->texture);
10298                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10299                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10300                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10301                                 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);
10302                         }
10303                         else
10304                         {
10305                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10306                                 R_Mesh_TexBind(0, layer->texture);
10307                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10308                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10309                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10310                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10311                                         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);
10312                                 else if (FAKELIGHT_ENABLED)
10313                                         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);
10314                                 else
10315                                         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);
10316                         }
10317                         break;
10318                 case TEXTURELAYERTYPE_TEXTURE:
10319                         // singletexture unlit texture with transparency support
10320                         R_Mesh_TexBind(0, layer->texture);
10321                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10322                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10323                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10324                         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);
10325                         break;
10326                 case TEXTURELAYERTYPE_FOG:
10327                         // singletexture fogging
10328                         if (layer->texture)
10329                         {
10330                                 R_Mesh_TexBind(0, layer->texture);
10331                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10332                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10333                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10334                         }
10335                         else
10336                         {
10337                                 R_Mesh_TexBind(0, 0);
10338                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10339                         }
10340                         // generate a color array for the fog pass
10341                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10342                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10343                         RSurf_DrawBatch();
10344                         break;
10345                 default:
10346                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10347                 }
10348         }
10349         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10350         {
10351                 GL_DepthFunc(GL_LEQUAL);
10352                 GL_AlphaTest(false);
10353         }
10354 }
10355
10356 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10357 {
10358         int vi;
10359         int j;
10360         r_vertexgeneric_t *batchvertex;
10361         float c[4];
10362
10363 //      R_Mesh_ResetTextureState();
10364         R_SetupShader_Generic_NoTexture(false, false);
10365
10366         if(rsurface.texture && rsurface.texture->currentskinframe)
10367         {
10368                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10369                 c[3] *= rsurface.texture->currentalpha;
10370         }
10371         else
10372         {
10373                 c[0] = 1;
10374                 c[1] = 0;
10375                 c[2] = 1;
10376                 c[3] = 1;
10377         }
10378
10379         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10380         {
10381                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10382                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10383                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10384         }
10385
10386         // brighten it up (as texture value 127 means "unlit")
10387         c[0] *= 2 * r_refdef.view.colorscale;
10388         c[1] *= 2 * r_refdef.view.colorscale;
10389         c[2] *= 2 * r_refdef.view.colorscale;
10390
10391         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10392                 c[3] *= r_wateralpha.value;
10393
10394         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10395         {
10396                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10397                 GL_DepthMask(false);
10398         }
10399         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10400         {
10401                 GL_BlendFunc(GL_ONE, GL_ONE);
10402                 GL_DepthMask(false);
10403         }
10404         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10405         {
10406                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10407                 GL_DepthMask(false);
10408         }
10409         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10410         {
10411                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10412                 GL_DepthMask(false);
10413         }
10414         else
10415         {
10416                 GL_BlendFunc(GL_ONE, GL_ZERO);
10417                 GL_DepthMask(writedepth);
10418         }
10419
10420         if (r_showsurfaces.integer == 3)
10421         {
10422                 rsurface.passcolor4f = NULL;
10423
10424                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10425                 {
10426                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10427
10428                         rsurface.passcolor4f = NULL;
10429                         rsurface.passcolor4f_vertexbuffer = 0;
10430                         rsurface.passcolor4f_bufferoffset = 0;
10431                 }
10432                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10433                 {
10434                         qboolean applycolor = true;
10435                         float one = 1.0;
10436
10437                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10438
10439                         r_refdef.lightmapintensity = 1;
10440                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10441                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10442                 }
10443                 else if (FAKELIGHT_ENABLED)
10444                 {
10445                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10446
10447                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10448                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10449                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10450                 }
10451                 else
10452                 {
10453                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10454
10455                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10456                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10457                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10458                 }
10459
10460                 if(!rsurface.passcolor4f)
10461                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10462
10463                 RSurf_DrawBatch_GL11_ApplyAmbient();
10464                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10465                 if(r_refdef.fogenabled)
10466                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10467                 RSurf_DrawBatch_GL11_ClampColor();
10468
10469                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10470                 R_SetupShader_Generic_NoTexture(false, false);
10471                 RSurf_DrawBatch();
10472         }
10473         else if (!r_refdef.view.showdebug)
10474         {
10475                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10476                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10477                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10478                 {
10479                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10480                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10481                 }
10482                 R_Mesh_PrepareVertices_Generic_Unlock();
10483                 RSurf_DrawBatch();
10484         }
10485         else if (r_showsurfaces.integer == 4)
10486         {
10487                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10488                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10489                 for (j = 0, vi = 0;j < rsurface.batchnumvertices;j++, vi++)
10490                 {
10491                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10492                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10493                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10494                 }
10495                 R_Mesh_PrepareVertices_Generic_Unlock();
10496                 RSurf_DrawBatch();
10497         }
10498         else if (r_showsurfaces.integer == 2)
10499         {
10500                 const int *e;
10501                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10502                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10503                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10504                 {
10505                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10506                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10507                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10508                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10509                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10510                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10511                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10512                 }
10513                 R_Mesh_PrepareVertices_Generic_Unlock();
10514                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10515         }
10516         else
10517         {
10518                 int texturesurfaceindex;
10519                 int k;
10520                 const msurface_t *surface;
10521                 float surfacecolor4f[4];
10522                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10523                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10524                 vi = 0;
10525                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10526                 {
10527                         surface = texturesurfacelist[texturesurfaceindex];
10528                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10529                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10530                         for (j = 0;j < surface->num_vertices;j++)
10531                         {
10532                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10533                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10534                                 vi++;
10535                         }
10536                 }
10537                 R_Mesh_PrepareVertices_Generic_Unlock();
10538                 RSurf_DrawBatch();
10539         }
10540 }
10541
10542 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10543 {
10544         CHECKGLERROR
10545         RSurf_SetupDepthAndCulling();
10546         if (r_showsurfaces.integer)
10547         {
10548                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10549                 return;
10550         }
10551         switch (vid.renderpath)
10552         {
10553         case RENDERPATH_GL20:
10554         case RENDERPATH_D3D9:
10555         case RENDERPATH_D3D10:
10556         case RENDERPATH_D3D11:
10557         case RENDERPATH_SOFT:
10558         case RENDERPATH_GLES2:
10559                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10560                 break;
10561         case RENDERPATH_GL13:
10562         case RENDERPATH_GLES1:
10563                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10564                 break;
10565         case RENDERPATH_GL11:
10566                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10567                 break;
10568         }
10569         CHECKGLERROR
10570 }
10571
10572 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10573 {
10574         CHECKGLERROR
10575         RSurf_SetupDepthAndCulling();
10576         if (r_showsurfaces.integer)
10577         {
10578                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10579                 return;
10580         }
10581         switch (vid.renderpath)
10582         {
10583         case RENDERPATH_GL20:
10584         case RENDERPATH_D3D9:
10585         case RENDERPATH_D3D10:
10586         case RENDERPATH_D3D11:
10587         case RENDERPATH_SOFT:
10588         case RENDERPATH_GLES2:
10589                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10590                 break;
10591         case RENDERPATH_GL13:
10592         case RENDERPATH_GLES1:
10593                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10594                 break;
10595         case RENDERPATH_GL11:
10596                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10597                 break;
10598         }
10599         CHECKGLERROR
10600 }
10601
10602 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10603 {
10604         int i, j;
10605         int texturenumsurfaces, endsurface;
10606         texture_t *texture;
10607         const msurface_t *surface;
10608         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10609
10610         // if the model is static it doesn't matter what value we give for
10611         // wantnormals and wanttangents, so this logic uses only rules applicable
10612         // to a model, knowing that they are meaningless otherwise
10613         if (ent == r_refdef.scene.worldentity)
10614                 RSurf_ActiveWorldEntity();
10615         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10616                 RSurf_ActiveModelEntity(ent, false, false, false);
10617         else
10618         {
10619                 switch (vid.renderpath)
10620                 {
10621                 case RENDERPATH_GL20:
10622                 case RENDERPATH_D3D9:
10623                 case RENDERPATH_D3D10:
10624                 case RENDERPATH_D3D11:
10625                 case RENDERPATH_SOFT:
10626                 case RENDERPATH_GLES2:
10627                         RSurf_ActiveModelEntity(ent, true, true, false);
10628                         break;
10629                 case RENDERPATH_GL11:
10630                 case RENDERPATH_GL13:
10631                 case RENDERPATH_GLES1:
10632                         RSurf_ActiveModelEntity(ent, true, false, false);
10633                         break;
10634                 }
10635         }
10636
10637         if (r_transparentdepthmasking.integer)
10638         {
10639                 qboolean setup = false;
10640                 for (i = 0;i < numsurfaces;i = j)
10641                 {
10642                         j = i + 1;
10643                         surface = rsurface.modelsurfaces + surfacelist[i];
10644                         texture = surface->texture;
10645                         rsurface.texture = R_GetCurrentTexture(texture);
10646                         rsurface.lightmaptexture = NULL;
10647                         rsurface.deluxemaptexture = NULL;
10648                         rsurface.uselightmaptexture = false;
10649                         // scan ahead until we find a different texture
10650                         endsurface = min(i + 1024, numsurfaces);
10651                         texturenumsurfaces = 0;
10652                         texturesurfacelist[texturenumsurfaces++] = surface;
10653                         for (;j < endsurface;j++)
10654                         {
10655                                 surface = rsurface.modelsurfaces + surfacelist[j];
10656                                 if (texture != surface->texture)
10657                                         break;
10658                                 texturesurfacelist[texturenumsurfaces++] = surface;
10659                         }
10660                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10661                                 continue;
10662                         // render the range of surfaces as depth
10663                         if (!setup)
10664                         {
10665                                 setup = true;
10666                                 GL_ColorMask(0,0,0,0);
10667                                 GL_Color(1,1,1,1);
10668                                 GL_DepthTest(true);
10669                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10670                                 GL_DepthMask(true);
10671 //                              R_Mesh_ResetTextureState();
10672                                 R_SetupShader_DepthOrShadow(false, false);
10673                         }
10674                         RSurf_SetupDepthAndCulling();
10675                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10676                         if (rsurface.batchvertex3fbuffer)
10677                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10678                         else
10679                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10680                         RSurf_DrawBatch();
10681                 }
10682                 if (setup)
10683                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10684         }
10685
10686         for (i = 0;i < numsurfaces;i = j)
10687         {
10688                 j = i + 1;
10689                 surface = rsurface.modelsurfaces + surfacelist[i];
10690                 texture = surface->texture;
10691                 rsurface.texture = R_GetCurrentTexture(texture);
10692                 // scan ahead until we find a different texture
10693                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10694                 texturenumsurfaces = 0;
10695                 texturesurfacelist[texturenumsurfaces++] = surface;
10696                 if(FAKELIGHT_ENABLED)
10697                 {
10698                         rsurface.lightmaptexture = NULL;
10699                         rsurface.deluxemaptexture = NULL;
10700                         rsurface.uselightmaptexture = false;
10701                         for (;j < endsurface;j++)
10702                         {
10703                                 surface = rsurface.modelsurfaces + surfacelist[j];
10704                                 if (texture != surface->texture)
10705                                         break;
10706                                 texturesurfacelist[texturenumsurfaces++] = surface;
10707                         }
10708                 }
10709                 else
10710                 {
10711                         rsurface.lightmaptexture = surface->lightmaptexture;
10712                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10713                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10714                         for (;j < endsurface;j++)
10715                         {
10716                                 surface = rsurface.modelsurfaces + surfacelist[j];
10717                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10718                                         break;
10719                                 texturesurfacelist[texturenumsurfaces++] = surface;
10720                         }
10721                 }
10722                 // render the range of surfaces
10723                 if (ent == r_refdef.scene.worldentity)
10724                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10725                 else
10726                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10727         }
10728         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10729 }
10730
10731 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10732 {
10733         // transparent surfaces get pushed off into the transparent queue
10734         int surfacelistindex;
10735         const msurface_t *surface;
10736         vec3_t tempcenter, center;
10737         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10738         {
10739                 surface = texturesurfacelist[surfacelistindex];
10740                 if (r_transparent_sortsurfacesbynearest.integer)
10741                 {
10742                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10743                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10744                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10745                 }
10746                 else
10747                 {
10748                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10749                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10750                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10751                 }
10752                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10753                 if (rsurface.entity->transparent_offset) // transparent offset
10754                 {
10755                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10756                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10757                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10758                 }
10759                 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);
10760         }
10761 }
10762
10763 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10764 {
10765         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10766                 return;
10767         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10768                 return;
10769         RSurf_SetupDepthAndCulling();
10770         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ALLOWMULTIDRAW, texturenumsurfaces, texturesurfacelist);
10771         if (rsurface.batchvertex3fbuffer)
10772                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10773         else
10774                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10775         RSurf_DrawBatch();
10776 }
10777
10778 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10779 {
10780         CHECKGLERROR
10781         if (depthonly)
10782                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10783         else if (prepass)
10784         {
10785                 if (!rsurface.texture->currentnumlayers)
10786                         return;
10787                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10788                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10789                 else
10790                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10791         }
10792         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10793                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10794         else if (!rsurface.texture->currentnumlayers)
10795                 return;
10796         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10797         {
10798                 // in the deferred case, transparent surfaces were queued during prepass
10799                 if (!r_shadow_usingdeferredprepass)
10800                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10801         }
10802         else
10803         {
10804                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10805                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10806         }
10807         CHECKGLERROR
10808 }
10809
10810 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10811 {
10812         int i, j;
10813         texture_t *texture;
10814         R_FrameData_SetMark();
10815         // break the surface list down into batches by texture and use of lightmapping
10816         for (i = 0;i < numsurfaces;i = j)
10817         {
10818                 j = i + 1;
10819                 // texture is the base texture pointer, rsurface.texture is the
10820                 // current frame/skin the texture is directing us to use (for example
10821                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10822                 // use skin 1 instead)
10823                 texture = surfacelist[i]->texture;
10824                 rsurface.texture = R_GetCurrentTexture(texture);
10825                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10826                 {
10827                         // if this texture is not the kind we want, skip ahead to the next one
10828                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10829                                 ;
10830                         continue;
10831                 }
10832                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10833                 {
10834                         rsurface.lightmaptexture = NULL;
10835                         rsurface.deluxemaptexture = NULL;
10836                         rsurface.uselightmaptexture = false;
10837                         // simply scan ahead until we find a different texture or lightmap state
10838                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10839                                 ;
10840                 }
10841                 else
10842                 {
10843                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10844                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10845                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10846                         // simply scan ahead until we find a different texture or lightmap state
10847                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10848                                 ;
10849                 }
10850                 // render the range of surfaces
10851                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10852         }
10853         R_FrameData_ReturnToMark();
10854 }
10855
10856 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10857 {
10858         CHECKGLERROR
10859         if (depthonly)
10860                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10861         else if (prepass)
10862         {
10863                 if (!rsurface.texture->currentnumlayers)
10864                         return;
10865                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10866                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10867                 else
10868                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10869         }
10870         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10871                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10872         else if (!rsurface.texture->currentnumlayers)
10873                 return;
10874         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10875         {
10876                 // in the deferred case, transparent surfaces were queued during prepass
10877                 if (!r_shadow_usingdeferredprepass)
10878                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10879         }
10880         else
10881         {
10882                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10883                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10884         }
10885         CHECKGLERROR
10886 }
10887
10888 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10889 {
10890         int i, j;
10891         texture_t *texture;
10892         R_FrameData_SetMark();
10893         // break the surface list down into batches by texture and use of lightmapping
10894         for (i = 0;i < numsurfaces;i = j)
10895         {
10896                 j = i + 1;
10897                 // texture is the base texture pointer, rsurface.texture is the
10898                 // current frame/skin the texture is directing us to use (for example
10899                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10900                 // use skin 1 instead)
10901                 texture = surfacelist[i]->texture;
10902                 rsurface.texture = R_GetCurrentTexture(texture);
10903                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10904                 {
10905                         // if this texture is not the kind we want, skip ahead to the next one
10906                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10907                                 ;
10908                         continue;
10909                 }
10910                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10911                 {
10912                         rsurface.lightmaptexture = NULL;
10913                         rsurface.deluxemaptexture = NULL;
10914                         rsurface.uselightmaptexture = false;
10915                         // simply scan ahead until we find a different texture or lightmap state
10916                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10917                                 ;
10918                 }
10919                 else
10920                 {
10921                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10922                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10923                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10924                         // simply scan ahead until we find a different texture or lightmap state
10925                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10926                                 ;
10927                 }
10928                 // render the range of surfaces
10929                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10930         }
10931         R_FrameData_ReturnToMark();
10932 }
10933
10934 float locboxvertex3f[6*4*3] =
10935 {
10936         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10937         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10938         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10939         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10940         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10941         1,0,0, 0,0,0, 0,1,0, 1,1,0
10942 };
10943
10944 unsigned short locboxelements[6*2*3] =
10945 {
10946          0, 1, 2, 0, 2, 3,
10947          4, 5, 6, 4, 6, 7,
10948          8, 9,10, 8,10,11,
10949         12,13,14, 12,14,15,
10950         16,17,18, 16,18,19,
10951         20,21,22, 20,22,23
10952 };
10953
10954 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10955 {
10956         int i, j;
10957         cl_locnode_t *loc = (cl_locnode_t *)ent;
10958         vec3_t mins, size;
10959         float vertex3f[6*4*3];
10960         CHECKGLERROR
10961         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10962         GL_DepthMask(false);
10963         GL_DepthRange(0, 1);
10964         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10965         GL_DepthTest(true);
10966         GL_CullFace(GL_NONE);
10967         R_EntityMatrix(&identitymatrix);
10968
10969 //      R_Mesh_ResetTextureState();
10970
10971         i = surfacelist[0];
10972         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10973                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10974                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10975                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10976
10977         if (VectorCompare(loc->mins, loc->maxs))
10978         {
10979                 VectorSet(size, 2, 2, 2);
10980                 VectorMA(loc->mins, -0.5f, size, mins);
10981         }
10982         else
10983         {
10984                 VectorCopy(loc->mins, mins);
10985                 VectorSubtract(loc->maxs, loc->mins, size);
10986         }
10987
10988         for (i = 0;i < 6*4*3;)
10989                 for (j = 0;j < 3;j++, i++)
10990                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10991
10992         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10993         R_SetupShader_Generic_NoTexture(false, false);
10994         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10995 }
10996
10997 void R_DrawLocs(void)
10998 {
10999         int index;
11000         cl_locnode_t *loc, *nearestloc;
11001         vec3_t center;
11002         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
11003         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
11004         {
11005                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
11006                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
11007         }
11008 }
11009
11010 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
11011 {
11012         if (decalsystem->decals)
11013                 Mem_Free(decalsystem->decals);
11014         memset(decalsystem, 0, sizeof(*decalsystem));
11015 }
11016
11017 static void R_DecalSystem_SpawnTriangle(decalsystem_t *decalsystem, const float *v0, const float *v1, const float *v2, const float *t0, const float *t1, const float *t2, const float *c0, const float *c1, const float *c2, int triangleindex, int surfaceindex, int decalsequence)
11018 {
11019         tridecal_t *decal;
11020         tridecal_t *decals;
11021         int i;
11022
11023         // expand or initialize the system
11024         if (decalsystem->maxdecals <= decalsystem->numdecals)
11025         {
11026                 decalsystem_t old = *decalsystem;
11027                 qboolean useshortelements;
11028                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
11029                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
11030                 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)));
11031                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
11032                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
11033                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
11034                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
11035                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
11036                 if (decalsystem->numdecals)
11037                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
11038                 if (old.decals)
11039                         Mem_Free(old.decals);
11040                 for (i = 0;i < decalsystem->maxdecals*3;i++)
11041                         decalsystem->element3i[i] = i;
11042                 if (useshortelements)
11043                         for (i = 0;i < decalsystem->maxdecals*3;i++)
11044                                 decalsystem->element3s[i] = i;
11045         }
11046
11047         // grab a decal and search for another free slot for the next one
11048         decals = decalsystem->decals;
11049         decal = decalsystem->decals + (i = decalsystem->freedecal++);
11050         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
11051                 ;
11052         decalsystem->freedecal = i;
11053         if (decalsystem->numdecals <= i)
11054                 decalsystem->numdecals = i + 1;
11055
11056         // initialize the decal
11057         decal->lived = 0;
11058         decal->triangleindex = triangleindex;
11059         decal->surfaceindex = surfaceindex;
11060         decal->decalsequence = decalsequence;
11061         decal->color4f[0][0] = c0[0];
11062         decal->color4f[0][1] = c0[1];
11063         decal->color4f[0][2] = c0[2];
11064         decal->color4f[0][3] = 1;
11065         decal->color4f[1][0] = c1[0];
11066         decal->color4f[1][1] = c1[1];
11067         decal->color4f[1][2] = c1[2];
11068         decal->color4f[1][3] = 1;
11069         decal->color4f[2][0] = c2[0];
11070         decal->color4f[2][1] = c2[1];
11071         decal->color4f[2][2] = c2[2];
11072         decal->color4f[2][3] = 1;
11073         decal->vertex3f[0][0] = v0[0];
11074         decal->vertex3f[0][1] = v0[1];
11075         decal->vertex3f[0][2] = v0[2];
11076         decal->vertex3f[1][0] = v1[0];
11077         decal->vertex3f[1][1] = v1[1];
11078         decal->vertex3f[1][2] = v1[2];
11079         decal->vertex3f[2][0] = v2[0];
11080         decal->vertex3f[2][1] = v2[1];
11081         decal->vertex3f[2][2] = v2[2];
11082         decal->texcoord2f[0][0] = t0[0];
11083         decal->texcoord2f[0][1] = t0[1];
11084         decal->texcoord2f[1][0] = t1[0];
11085         decal->texcoord2f[1][1] = t1[1];
11086         decal->texcoord2f[2][0] = t2[0];
11087         decal->texcoord2f[2][1] = t2[1];
11088         TriangleNormal(v0, v1, v2, decal->plane);
11089         VectorNormalize(decal->plane);
11090         decal->plane[3] = DotProduct(v0, decal->plane);
11091 }
11092
11093 extern cvar_t cl_decals_bias;
11094 extern cvar_t cl_decals_models;
11095 extern cvar_t cl_decals_newsystem_intensitymultiplier;
11096 // baseparms, parms, temps
11097 static void R_DecalSystem_SplatTriangle(decalsystem_t *decalsystem, float r, float g, float b, float a, float s1, float t1, float s2, float t2, int decalsequence, qboolean dynamic, float (*planes)[4], matrix4x4_t *projection, int triangleindex, int surfaceindex)
11098 {
11099         int cornerindex;
11100         int index;
11101         float v[9][3];
11102         const float *vertex3f;
11103         const float *normal3f;
11104         int numpoints;
11105         float points[2][9][3];
11106         float temp[3];
11107         float tc[9][2];
11108         float f;
11109         float c[9][4];
11110         const int *e;
11111
11112         e = rsurface.modelelement3i + 3*triangleindex;
11113
11114         vertex3f = rsurface.modelvertex3f;
11115         normal3f = rsurface.modelnormal3f;
11116
11117         if (normal3f)
11118         {
11119                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11120                 {
11121                         index = 3*e[cornerindex];
11122                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
11123                 }
11124         }
11125         else
11126         {
11127                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11128                 {
11129                         index = 3*e[cornerindex];
11130                         VectorCopy(vertex3f + index, v[cornerindex]);
11131                 }
11132         }
11133
11134         // cull backfaces
11135         //TriangleNormal(v[0], v[1], v[2], normal);
11136         //if (DotProduct(normal, localnormal) < 0.0f)
11137         //      continue;
11138         // clip by each of the box planes formed from the projection matrix
11139         // if anything survives, we emit the decal
11140         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]);
11141         if (numpoints < 3)
11142                 return;
11143         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]);
11144         if (numpoints < 3)
11145                 return;
11146         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]);
11147         if (numpoints < 3)
11148                 return;
11149         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]);
11150         if (numpoints < 3)
11151                 return;
11152         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]);
11153         if (numpoints < 3)
11154                 return;
11155         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]);
11156         if (numpoints < 3)
11157                 return;
11158         // some part of the triangle survived, so we have to accept it...
11159         if (dynamic)
11160         {
11161                 // dynamic always uses the original triangle
11162                 numpoints = 3;
11163                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
11164                 {
11165                         index = 3*e[cornerindex];
11166                         VectorCopy(vertex3f + index, v[cornerindex]);
11167                 }
11168         }
11169         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
11170         {
11171                 // convert vertex positions to texcoords
11172                 Matrix4x4_Transform(projection, v[cornerindex], temp);
11173                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
11174                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
11175                 // calculate distance fade from the projection origin
11176                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
11177                 f = bound(0.0f, f, 1.0f);
11178                 c[cornerindex][0] = r * f;
11179                 c[cornerindex][1] = g * f;
11180                 c[cornerindex][2] = b * f;
11181                 c[cornerindex][3] = 1.0f;
11182                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
11183         }
11184         if (dynamic)
11185                 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);
11186         else
11187                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
11188                         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);
11189 }
11190 static void R_DecalSystem_SplatEntity(entity_render_t *ent, const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
11191 {
11192         matrix4x4_t projection;
11193         decalsystem_t *decalsystem;
11194         qboolean dynamic;
11195         dp_model_t *model;
11196         const msurface_t *surface;
11197         const msurface_t *surfaces;
11198         const int *surfacelist;
11199         const texture_t *texture;
11200         int numtriangles;
11201         int numsurfacelist;
11202         int surfacelistindex;
11203         int surfaceindex;
11204         int triangleindex;
11205         float localorigin[3];
11206         float localnormal[3];
11207         float localmins[3];
11208         float localmaxs[3];
11209         float localsize;
11210         //float normal[3];
11211         float planes[6][4];
11212         float angles[3];
11213         bih_t *bih;
11214         int bih_triangles_count;
11215         int bih_triangles[256];
11216         int bih_surfaces[256];
11217
11218         decalsystem = &ent->decalsystem;
11219         model = ent->model;
11220         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
11221         {
11222                 R_DecalSystem_Reset(&ent->decalsystem);
11223                 return;
11224         }
11225
11226         if (!model->brush.data_leafs && !cl_decals_models.integer)
11227         {
11228                 if (decalsystem->model)
11229                         R_DecalSystem_Reset(decalsystem);
11230                 return;
11231         }
11232
11233         if (decalsystem->model != model)
11234                 R_DecalSystem_Reset(decalsystem);
11235         decalsystem->model = model;
11236
11237         RSurf_ActiveModelEntity(ent, true, false, false);
11238
11239         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
11240         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
11241         VectorNormalize(localnormal);
11242         localsize = worldsize*rsurface.inversematrixscale;
11243         localmins[0] = localorigin[0] - localsize;
11244         localmins[1] = localorigin[1] - localsize;
11245         localmins[2] = localorigin[2] - localsize;
11246         localmaxs[0] = localorigin[0] + localsize;
11247         localmaxs[1] = localorigin[1] + localsize;
11248         localmaxs[2] = localorigin[2] + localsize;
11249
11250         //VectorCopy(localnormal, planes[4]);
11251         //VectorVectors(planes[4], planes[2], planes[0]);
11252         AnglesFromVectors(angles, localnormal, NULL, false);
11253         AngleVectors(angles, planes[0], planes[2], planes[4]);
11254         VectorNegate(planes[0], planes[1]);
11255         VectorNegate(planes[2], planes[3]);
11256         VectorNegate(planes[4], planes[5]);
11257         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11258         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11259         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11260         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11261         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11262         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11263
11264 #if 1
11265 // works
11266 {
11267         matrix4x4_t forwardprojection;
11268         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11269         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11270 }
11271 #else
11272 // broken
11273 {
11274         float projectionvector[4][3];
11275         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11276         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11277         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11278         projectionvector[0][0] = planes[0][0] * ilocalsize;
11279         projectionvector[0][1] = planes[1][0] * ilocalsize;
11280         projectionvector[0][2] = planes[2][0] * ilocalsize;
11281         projectionvector[1][0] = planes[0][1] * ilocalsize;
11282         projectionvector[1][1] = planes[1][1] * ilocalsize;
11283         projectionvector[1][2] = planes[2][1] * ilocalsize;
11284         projectionvector[2][0] = planes[0][2] * ilocalsize;
11285         projectionvector[2][1] = planes[1][2] * ilocalsize;
11286         projectionvector[2][2] = planes[2][2] * ilocalsize;
11287         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11288         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11289         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11290         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11291 }
11292 #endif
11293
11294         dynamic = model->surfmesh.isanimated;
11295         numsurfacelist = model->nummodelsurfaces;
11296         surfacelist = model->sortedmodelsurfaces;
11297         surfaces = model->data_surfaces;
11298
11299         bih = NULL;
11300         bih_triangles_count = -1;
11301         if(!dynamic)
11302         {
11303                 if(model->render_bih.numleafs)
11304                         bih = &model->render_bih;
11305                 else if(model->collision_bih.numleafs)
11306                         bih = &model->collision_bih;
11307         }
11308         if(bih)
11309                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11310         if(bih_triangles_count == 0)
11311                 return;
11312         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11313                 return;
11314         if(bih_triangles_count > 0)
11315         {
11316                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11317                 {
11318                         surfaceindex = bih_surfaces[triangleindex];
11319                         surface = surfaces + surfaceindex;
11320                         texture = surface->texture;
11321                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11322                                 continue;
11323                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11324                                 continue;
11325                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11326                 }
11327         }
11328         else
11329         {
11330                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11331                 {
11332                         surfaceindex = surfacelist[surfacelistindex];
11333                         surface = surfaces + surfaceindex;
11334                         // check cull box first because it rejects more than any other check
11335                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11336                                 continue;
11337                         // skip transparent surfaces
11338                         texture = surface->texture;
11339                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11340                                 continue;
11341                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11342                                 continue;
11343                         numtriangles = surface->num_triangles;
11344                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11345                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11346                 }
11347         }
11348 }
11349
11350 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11351 static void R_DecalSystem_ApplySplatEntities(const vec3_t worldorigin, const vec3_t worldnormal, float r, float g, float b, float a, float s1, float t1, float s2, float t2, float worldsize, int decalsequence)
11352 {
11353         int renderentityindex;
11354         float worldmins[3];
11355         float worldmaxs[3];
11356         entity_render_t *ent;
11357
11358         if (!cl_decals_newsystem.integer)
11359                 return;
11360
11361         worldmins[0] = worldorigin[0] - worldsize;
11362         worldmins[1] = worldorigin[1] - worldsize;
11363         worldmins[2] = worldorigin[2] - worldsize;
11364         worldmaxs[0] = worldorigin[0] + worldsize;
11365         worldmaxs[1] = worldorigin[1] + worldsize;
11366         worldmaxs[2] = worldorigin[2] + worldsize;
11367
11368         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11369
11370         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11371         {
11372                 ent = r_refdef.scene.entities[renderentityindex];
11373                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11374                         continue;
11375
11376                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11377         }
11378 }
11379
11380 typedef struct r_decalsystem_splatqueue_s
11381 {
11382         vec3_t worldorigin;
11383         vec3_t worldnormal;
11384         float color[4];
11385         float tcrange[4];
11386         float worldsize;
11387         int decalsequence;
11388 }
11389 r_decalsystem_splatqueue_t;
11390
11391 int r_decalsystem_numqueued = 0;
11392 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11393
11394 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)
11395 {
11396         r_decalsystem_splatqueue_t *queue;
11397
11398         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11399                 return;
11400
11401         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11402         VectorCopy(worldorigin, queue->worldorigin);
11403         VectorCopy(worldnormal, queue->worldnormal);
11404         Vector4Set(queue->color, r, g, b, a);
11405         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11406         queue->worldsize = worldsize;
11407         queue->decalsequence = cl.decalsequence++;
11408 }
11409
11410 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11411 {
11412         int i;
11413         r_decalsystem_splatqueue_t *queue;
11414
11415         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11416                 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);
11417         r_decalsystem_numqueued = 0;
11418 }
11419
11420 extern cvar_t cl_decals_max;
11421 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11422 {
11423         int i;
11424         decalsystem_t *decalsystem = &ent->decalsystem;
11425         int numdecals;
11426         int killsequence;
11427         tridecal_t *decal;
11428         float frametime;
11429         float lifetime;
11430
11431         if (!decalsystem->numdecals)
11432                 return;
11433
11434         if (r_showsurfaces.integer)
11435                 return;
11436
11437         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11438         {
11439                 R_DecalSystem_Reset(decalsystem);
11440                 return;
11441         }
11442
11443         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11444         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11445
11446         if (decalsystem->lastupdatetime)
11447                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11448         else
11449                 frametime = 0;
11450         decalsystem->lastupdatetime = r_refdef.scene.time;
11451         numdecals = decalsystem->numdecals;
11452
11453         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11454         {
11455                 if (decal->color4f[0][3])
11456                 {
11457                         decal->lived += frametime;
11458                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11459                         {
11460                                 memset(decal, 0, sizeof(*decal));
11461                                 if (decalsystem->freedecal > i)
11462                                         decalsystem->freedecal = i;
11463                         }
11464                 }
11465         }
11466         decal = decalsystem->decals;
11467         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11468                 numdecals--;
11469
11470         // collapse the array by shuffling the tail decals into the gaps
11471         for (;;)
11472         {
11473                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11474                         decalsystem->freedecal++;
11475                 if (decalsystem->freedecal == numdecals)
11476                         break;
11477                 decal[decalsystem->freedecal] = decal[--numdecals];
11478         }
11479
11480         decalsystem->numdecals = numdecals;
11481
11482         if (numdecals <= 0)
11483         {
11484                 // if there are no decals left, reset decalsystem
11485                 R_DecalSystem_Reset(decalsystem);
11486         }
11487 }
11488
11489 extern skinframe_t *decalskinframe;
11490 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11491 {
11492         int i;
11493         decalsystem_t *decalsystem = &ent->decalsystem;
11494         int numdecals;
11495         tridecal_t *decal;
11496         float faderate;
11497         float alpha;
11498         float *v3f;
11499         float *c4f;
11500         float *t2f;
11501         const int *e;
11502         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11503         int numtris = 0;
11504
11505         numdecals = decalsystem->numdecals;
11506         if (!numdecals)
11507                 return;
11508
11509         if (r_showsurfaces.integer)
11510                 return;
11511
11512         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11513         {
11514                 R_DecalSystem_Reset(decalsystem);
11515                 return;
11516         }
11517
11518         // if the model is static it doesn't matter what value we give for
11519         // wantnormals and wanttangents, so this logic uses only rules applicable
11520         // to a model, knowing that they are meaningless otherwise
11521         if (ent == r_refdef.scene.worldentity)
11522                 RSurf_ActiveWorldEntity();
11523         else
11524                 RSurf_ActiveModelEntity(ent, false, false, false);
11525
11526         decalsystem->lastupdatetime = r_refdef.scene.time;
11527
11528         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11529
11530         // update vertex positions for animated models
11531         v3f = decalsystem->vertex3f;
11532         c4f = decalsystem->color4f;
11533         t2f = decalsystem->texcoord2f;
11534         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11535         {
11536                 if (!decal->color4f[0][3])
11537                         continue;
11538
11539                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11540                         continue;
11541
11542                 // skip backfaces
11543                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11544                         continue;
11545
11546                 // update color values for fading decals
11547                 if (decal->lived >= cl_decals_time.value)
11548                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11549                 else
11550                         alpha = 1.0f;
11551
11552                 c4f[ 0] = decal->color4f[0][0] * alpha;
11553                 c4f[ 1] = decal->color4f[0][1] * alpha;
11554                 c4f[ 2] = decal->color4f[0][2] * alpha;
11555                 c4f[ 3] = 1;
11556                 c4f[ 4] = decal->color4f[1][0] * alpha;
11557                 c4f[ 5] = decal->color4f[1][1] * alpha;
11558                 c4f[ 6] = decal->color4f[1][2] * alpha;
11559                 c4f[ 7] = 1;
11560                 c4f[ 8] = decal->color4f[2][0] * alpha;
11561                 c4f[ 9] = decal->color4f[2][1] * alpha;
11562                 c4f[10] = decal->color4f[2][2] * alpha;
11563                 c4f[11] = 1;
11564
11565                 t2f[0] = decal->texcoord2f[0][0];
11566                 t2f[1] = decal->texcoord2f[0][1];
11567                 t2f[2] = decal->texcoord2f[1][0];
11568                 t2f[3] = decal->texcoord2f[1][1];
11569                 t2f[4] = decal->texcoord2f[2][0];
11570                 t2f[5] = decal->texcoord2f[2][1];
11571
11572                 // update vertex positions for animated models
11573                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11574                 {
11575                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11576                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11577                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11578                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11579                 }
11580                 else
11581                 {
11582                         VectorCopy(decal->vertex3f[0], v3f);
11583                         VectorCopy(decal->vertex3f[1], v3f + 3);
11584                         VectorCopy(decal->vertex3f[2], v3f + 6);
11585                 }
11586
11587                 if (r_refdef.fogenabled)
11588                 {
11589                         alpha = RSurf_FogVertex(v3f);
11590                         VectorScale(c4f, alpha, c4f);
11591                         alpha = RSurf_FogVertex(v3f + 3);
11592                         VectorScale(c4f + 4, alpha, c4f + 4);
11593                         alpha = RSurf_FogVertex(v3f + 6);
11594                         VectorScale(c4f + 8, alpha, c4f + 8);
11595                 }
11596
11597                 v3f += 9;
11598                 c4f += 12;
11599                 t2f += 6;
11600                 numtris++;
11601         }
11602
11603         if (numtris > 0)
11604         {
11605                 r_refdef.stats.drawndecals += numtris;
11606
11607                 // now render the decals all at once
11608                 // (this assumes they all use one particle font texture!)
11609                 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);
11610 //              R_Mesh_ResetTextureState();
11611                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11612                 GL_DepthMask(false);
11613                 GL_DepthRange(0, 1);
11614                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11615                 GL_DepthTest(true);
11616                 GL_CullFace(GL_NONE);
11617                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11618                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11619                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11620         }
11621 }
11622
11623 static void R_DrawModelDecals(void)
11624 {
11625         int i, numdecals;
11626
11627         // fade faster when there are too many decals
11628         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11629         for (i = 0;i < r_refdef.scene.numentities;i++)
11630                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11631
11632         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11633         for (i = 0;i < r_refdef.scene.numentities;i++)
11634                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11635                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11636
11637         R_DecalSystem_ApplySplatEntitiesQueue();
11638
11639         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11640         for (i = 0;i < r_refdef.scene.numentities;i++)
11641                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11642
11643         r_refdef.stats.totaldecals += numdecals;
11644
11645         if (r_showsurfaces.integer)
11646                 return;
11647
11648         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11649
11650         for (i = 0;i < r_refdef.scene.numentities;i++)
11651         {
11652                 if (!r_refdef.viewcache.entityvisible[i])
11653                         continue;
11654                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11655                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11656         }
11657 }
11658
11659 extern cvar_t mod_collision_bih;
11660 static void R_DrawDebugModel(void)
11661 {
11662         entity_render_t *ent = rsurface.entity;
11663         int i, j, k, l, flagsmask;
11664         const msurface_t *surface;
11665         dp_model_t *model = ent->model;
11666         vec3_t v;
11667
11668         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11669                 return;
11670
11671         if (r_showoverdraw.value > 0)
11672         {
11673                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11674                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11675                 R_SetupShader_Generic_NoTexture(false, false);
11676                 GL_DepthTest(false);
11677                 GL_DepthMask(false);
11678                 GL_DepthRange(0, 1);
11679                 GL_BlendFunc(GL_ONE, GL_ONE);
11680                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11681                 {
11682                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11683                                 continue;
11684                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11685                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11686                         {
11687                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11688                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11689                                 if (!rsurface.texture->currentlayers->depthmask)
11690                                         GL_Color(c, 0, 0, 1.0f);
11691                                 else if (ent == r_refdef.scene.worldentity)
11692                                         GL_Color(c, c, c, 1.0f);
11693                                 else
11694                                         GL_Color(0, c, 0, 1.0f);
11695                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11696                                 RSurf_DrawBatch();
11697                         }
11698                 }
11699                 rsurface.texture = NULL;
11700         }
11701
11702         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11703
11704 //      R_Mesh_ResetTextureState();
11705         R_SetupShader_Generic_NoTexture(false, false);
11706         GL_DepthRange(0, 1);
11707         GL_DepthTest(!r_showdisabledepthtest.integer);
11708         GL_DepthMask(false);
11709         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11710
11711         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11712         {
11713                 int triangleindex;
11714                 int bihleafindex;
11715                 qboolean cullbox = false;
11716                 const q3mbrush_t *brush;
11717                 const bih_t *bih = &model->collision_bih;
11718                 const bih_leaf_t *bihleaf;
11719                 float vertex3f[3][3];
11720                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11721                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11722                 {
11723                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11724                                 continue;
11725                         switch (bihleaf->type)
11726                         {
11727                         case BIH_BRUSH:
11728                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11729                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11730                                 {
11731                                         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);
11732                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11733                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11734                                 }
11735                                 break;
11736                         case BIH_COLLISIONTRIANGLE:
11737                                 triangleindex = bihleaf->itemindex;
11738                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11739                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11740                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11741                                 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);
11742                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11743                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11744                                 break;
11745                         case BIH_RENDERTRIANGLE:
11746                                 triangleindex = bihleaf->itemindex;
11747                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11748                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11749                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11750                                 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);
11751                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11752                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11753                                 break;
11754                         }
11755                 }
11756         }
11757
11758         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11759
11760 #ifndef USE_GLES2
11761         if (r_showtris.integer && qglPolygonMode)
11762         {
11763                 if (r_showdisabledepthtest.integer)
11764                 {
11765                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11766                         GL_DepthMask(false);
11767                 }
11768                 else
11769                 {
11770                         GL_BlendFunc(GL_ONE, GL_ZERO);
11771                         GL_DepthMask(true);
11772                 }
11773                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11774                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11775                 {
11776                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11777                                 continue;
11778                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11779                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11780                         {
11781                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11782                                 if (!rsurface.texture->currentlayers->depthmask)
11783                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11784                                 else if (ent == r_refdef.scene.worldentity)
11785                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11786                                 else
11787                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11788                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11789                                 RSurf_DrawBatch();
11790                         }
11791                 }
11792                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11793                 rsurface.texture = NULL;
11794         }
11795
11796         if (r_shownormals.value != 0 && qglBegin)
11797         {
11798                 if (r_showdisabledepthtest.integer)
11799                 {
11800                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11801                         GL_DepthMask(false);
11802                 }
11803                 else
11804                 {
11805                         GL_BlendFunc(GL_ONE, GL_ZERO);
11806                         GL_DepthMask(true);
11807                 }
11808                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11809                 {
11810                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11811                                 continue;
11812                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11813                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11814                         {
11815                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11816                                 qglBegin(GL_LINES);
11817                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11818                                 {
11819                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11820                                         {
11821                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11822                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11823                                                 qglVertex3f(v[0], v[1], v[2]);
11824                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11825                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11826                                                 qglVertex3f(v[0], v[1], v[2]);
11827                                         }
11828                                 }
11829                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11830                                 {
11831                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11832                                         {
11833                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11834                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11835                                                 qglVertex3f(v[0], v[1], v[2]);
11836                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11837                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11838                                                 qglVertex3f(v[0], v[1], v[2]);
11839                                         }
11840                                 }
11841                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11842                                 {
11843                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11844                                         {
11845                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11846                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11847                                                 qglVertex3f(v[0], v[1], v[2]);
11848                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11849                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11850                                                 qglVertex3f(v[0], v[1], v[2]);
11851                                         }
11852                                 }
11853                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11854                                 {
11855                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11856                                         {
11857                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11858                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11859                                                 qglVertex3f(v[0], v[1], v[2]);
11860                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11861                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11862                                                 qglVertex3f(v[0], v[1], v[2]);
11863                                         }
11864                                 }
11865                                 qglEnd();
11866                                 CHECKGLERROR
11867                         }
11868                 }
11869                 rsurface.texture = NULL;
11870         }
11871 #endif
11872 }
11873
11874 int r_maxsurfacelist = 0;
11875 const msurface_t **r_surfacelist = NULL;
11876 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11877 {
11878         int i, j, endj, flagsmask;
11879         dp_model_t *model = r_refdef.scene.worldmodel;
11880         msurface_t *surfaces;
11881         unsigned char *update;
11882         int numsurfacelist = 0;
11883         if (model == NULL)
11884                 return;
11885
11886         if (r_maxsurfacelist < model->num_surfaces)
11887         {
11888                 r_maxsurfacelist = model->num_surfaces;
11889                 if (r_surfacelist)
11890                         Mem_Free((msurface_t**)r_surfacelist);
11891                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11892         }
11893
11894         RSurf_ActiveWorldEntity();
11895
11896         surfaces = model->data_surfaces;
11897         update = model->brushq1.lightmapupdateflags;
11898
11899         // update light styles on this submodel
11900         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11901         {
11902                 model_brush_lightstyleinfo_t *style;
11903                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11904                 {
11905                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11906                         {
11907                                 int *list = style->surfacelist;
11908                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11909                                 for (j = 0;j < style->numsurfaces;j++)
11910                                         update[list[j]] = true;
11911                         }
11912                 }
11913         }
11914
11915         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11916
11917         if (debug)
11918         {
11919                 R_DrawDebugModel();
11920                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11921                 return;
11922         }
11923
11924         rsurface.lightmaptexture = NULL;
11925         rsurface.deluxemaptexture = NULL;
11926         rsurface.uselightmaptexture = false;
11927         rsurface.texture = NULL;
11928         rsurface.rtlight = NULL;
11929         numsurfacelist = 0;
11930         // add visible surfaces to draw list
11931         for (i = 0;i < model->nummodelsurfaces;i++)
11932         {
11933                 j = model->sortedmodelsurfaces[i];
11934                 if (r_refdef.viewcache.world_surfacevisible[j])
11935                         r_surfacelist[numsurfacelist++] = surfaces + j;
11936         }
11937         // update lightmaps if needed
11938         if (model->brushq1.firstrender)
11939         {
11940                 model->brushq1.firstrender = false;
11941                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11942                         if (update[j])
11943                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11944         }
11945         else if (update)
11946         {
11947                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11948                         if (r_refdef.viewcache.world_surfacevisible[j])
11949                                 if (update[j])
11950                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11951         }
11952         // don't do anything if there were no surfaces
11953         if (!numsurfacelist)
11954         {
11955                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11956                 return;
11957         }
11958         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11959
11960         // add to stats if desired
11961         if (r_speeds.integer && !skysurfaces && !depthonly)
11962         {
11963                 r_refdef.stats.world_surfaces += numsurfacelist;
11964                 for (j = 0;j < numsurfacelist;j++)
11965                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11966         }
11967
11968         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11969 }
11970
11971 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11972 {
11973         int i, j, endj, flagsmask;
11974         dp_model_t *model = ent->model;
11975         msurface_t *surfaces;
11976         unsigned char *update;
11977         int numsurfacelist = 0;
11978         if (model == NULL)
11979                 return;
11980
11981         if (r_maxsurfacelist < model->num_surfaces)
11982         {
11983                 r_maxsurfacelist = model->num_surfaces;
11984                 if (r_surfacelist)
11985                         Mem_Free((msurface_t **)r_surfacelist);
11986                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11987         }
11988
11989         // if the model is static it doesn't matter what value we give for
11990         // wantnormals and wanttangents, so this logic uses only rules applicable
11991         // to a model, knowing that they are meaningless otherwise
11992         if (ent == r_refdef.scene.worldentity)
11993                 RSurf_ActiveWorldEntity();
11994         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11995                 RSurf_ActiveModelEntity(ent, false, false, false);
11996         else if (prepass)
11997                 RSurf_ActiveModelEntity(ent, true, true, true);
11998         else if (depthonly)
11999         {
12000                 switch (vid.renderpath)
12001                 {
12002                 case RENDERPATH_GL20:
12003                 case RENDERPATH_D3D9:
12004                 case RENDERPATH_D3D10:
12005                 case RENDERPATH_D3D11:
12006                 case RENDERPATH_SOFT:
12007                 case RENDERPATH_GLES2:
12008                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
12009                         break;
12010                 case RENDERPATH_GL11:
12011                 case RENDERPATH_GL13:
12012                 case RENDERPATH_GLES1:
12013                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
12014                         break;
12015                 }
12016         }
12017         else
12018         {
12019                 switch (vid.renderpath)
12020                 {
12021                 case RENDERPATH_GL20:
12022                 case RENDERPATH_D3D9:
12023                 case RENDERPATH_D3D10:
12024                 case RENDERPATH_D3D11:
12025                 case RENDERPATH_SOFT:
12026                 case RENDERPATH_GLES2:
12027                         RSurf_ActiveModelEntity(ent, true, true, false);
12028                         break;
12029                 case RENDERPATH_GL11:
12030                 case RENDERPATH_GL13:
12031                 case RENDERPATH_GLES1:
12032                         RSurf_ActiveModelEntity(ent, true, false, false);
12033                         break;
12034                 }
12035         }
12036
12037         surfaces = model->data_surfaces;
12038         update = model->brushq1.lightmapupdateflags;
12039
12040         // update light styles
12041         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
12042         {
12043                 model_brush_lightstyleinfo_t *style;
12044                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
12045                 {
12046                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
12047                         {
12048                                 int *list = style->surfacelist;
12049                                 style->value = r_refdef.scene.lightstylevalue[style->style];
12050                                 for (j = 0;j < style->numsurfaces;j++)
12051                                         update[list[j]] = true;
12052                         }
12053                 }
12054         }
12055
12056         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
12057
12058         if (debug)
12059         {
12060                 R_DrawDebugModel();
12061                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12062                 return;
12063         }
12064
12065         rsurface.lightmaptexture = NULL;
12066         rsurface.deluxemaptexture = NULL;
12067         rsurface.uselightmaptexture = false;
12068         rsurface.texture = NULL;
12069         rsurface.rtlight = NULL;
12070         numsurfacelist = 0;
12071         // add visible surfaces to draw list
12072         for (i = 0;i < model->nummodelsurfaces;i++)
12073                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
12074         // don't do anything if there were no surfaces
12075         if (!numsurfacelist)
12076         {
12077                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12078                 return;
12079         }
12080         // update lightmaps if needed
12081         if (update)
12082         {
12083                 int updated = 0;
12084                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
12085                 {
12086                         if (update[j])
12087                         {
12088                                 updated++;
12089                                 R_BuildLightMap(ent, surfaces + j);
12090                         }
12091                 }
12092         }
12093
12094         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
12095
12096         // add to stats if desired
12097         if (r_speeds.integer && !skysurfaces && !depthonly)
12098         {
12099                 r_refdef.stats.entities_surfaces += numsurfacelist;
12100                 for (j = 0;j < numsurfacelist;j++)
12101                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
12102         }
12103
12104         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
12105 }
12106
12107 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
12108 {
12109         static texture_t texture;
12110         static msurface_t surface;
12111         const msurface_t *surfacelist = &surface;
12112
12113         // fake enough texture and surface state to render this geometry
12114
12115         texture.update_lastrenderframe = -1; // regenerate this texture
12116         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
12117         texture.currentskinframe = skinframe;
12118         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
12119         texture.offsetmapping = OFFSETMAPPING_OFF;
12120         texture.offsetscale = 1;
12121         texture.specularscalemod = 1;
12122         texture.specularpowermod = 1;
12123         texture.transparentsort = TRANSPARENTSORT_DISTANCE;
12124         // WHEN ADDING DEFAULTS HERE, REMEMBER TO PUT DEFAULTS IN ALL LOADERS
12125         // JUST GREP FOR "specularscalemod = 1".
12126
12127         surface.texture = &texture;
12128         surface.num_triangles = numtriangles;
12129         surface.num_firsttriangle = firsttriangle;
12130         surface.num_vertices = numvertices;
12131         surface.num_firstvertex = firstvertex;
12132
12133         // now render it
12134         rsurface.texture = R_GetCurrentTexture(surface.texture);
12135         rsurface.lightmaptexture = NULL;
12136         rsurface.deluxemaptexture = NULL;
12137         rsurface.uselightmaptexture = false;
12138         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12139 }
12140
12141 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)
12142 {
12143         static msurface_t surface;
12144         const msurface_t *surfacelist = &surface;
12145
12146         // fake enough texture and surface state to render this geometry
12147         surface.texture = texture;
12148         surface.num_triangles = numtriangles;
12149         surface.num_firsttriangle = firsttriangle;
12150         surface.num_vertices = numvertices;
12151         surface.num_firstvertex = firstvertex;
12152
12153         // now render it
12154         rsurface.texture = R_GetCurrentTexture(surface.texture);
12155         rsurface.lightmaptexture = NULL;
12156         rsurface.deluxemaptexture = NULL;
12157         rsurface.uselightmaptexture = false;
12158         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
12159 }