]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
don't honor cl.paused or host_framerate in demo playback (to fix Malice
[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_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
124 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"};
125 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"};
126 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
127 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
128 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
129 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
130 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
131 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"};
132 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
133 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
134 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
135 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
136 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
137
138 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
139 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
140 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
141 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
142 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
143 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
144 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
145 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
146
147 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)"};
148 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"};
149
150 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
151 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
152 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
153
154 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"};
155 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"};
156 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"};
157 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
158 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
159 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"};
160 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)"};
161 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)"};
162 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
163
164 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)"};
165 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
166 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)"};
167 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
168 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)"};
169 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)"};
170 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
171 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"};
172 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."};
173 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
174 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)"};
175 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)"};
176 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)"};
177 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)"};
178 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)"};
179 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)"};
180 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)"};
181 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)"};
182
183 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)"};
184 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
185 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"};
186 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
187 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
188 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
189 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"};
190 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"};
191 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)"};
192
193 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
194 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
195 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
196 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
197
198 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
199 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
200
201 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
202 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
203 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
204 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
205 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
206 cvar_t r_bloom_scenebrightness = {CVAR_SAVE, "r_bloom_scenebrightness", "1", "global rendering brightness when bloom is enabled"};
207
208 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
209 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
210 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
211 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
212 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
213 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
214 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
215 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
216 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
217 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
218
219 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"};
220
221 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"};
222
223 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
224
225 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
226
227 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
228 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"};
229
230 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."};
231
232 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)"};
233
234 extern cvar_t v_glslgamma;
235 extern cvar_t v_glslgamma_2d;
236
237 extern qboolean v_flipped_state;
238
239 r_framebufferstate_t r_fb;
240
241 /// shadow volume bsp struct with automatically growing nodes buffer
242 svbsp_t r_svbsp;
243
244 rtexture_t *r_texture_blanknormalmap;
245 rtexture_t *r_texture_white;
246 rtexture_t *r_texture_grey128;
247 rtexture_t *r_texture_black;
248 rtexture_t *r_texture_notexture;
249 rtexture_t *r_texture_whitecube;
250 rtexture_t *r_texture_normalizationcube;
251 rtexture_t *r_texture_fogattenuation;
252 rtexture_t *r_texture_fogheighttexture;
253 rtexture_t *r_texture_gammaramps;
254 unsigned int r_texture_gammaramps_serial;
255 //rtexture_t *r_texture_fogintensity;
256 rtexture_t *r_texture_reflectcube;
257
258 // TODO: hash lookups?
259 typedef struct cubemapinfo_s
260 {
261         char basename[64];
262         rtexture_t *texture;
263 }
264 cubemapinfo_t;
265
266 int r_texture_numcubemaps;
267 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
268
269 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
270 unsigned int r_numqueries;
271 unsigned int r_maxqueries;
272
273 typedef struct r_qwskincache_s
274 {
275         char name[MAX_QPATH];
276         skinframe_t *skinframe;
277 }
278 r_qwskincache_t;
279
280 static r_qwskincache_t *r_qwskincache;
281 static int r_qwskincache_size;
282
283 /// vertex coordinates for a quad that covers the screen exactly
284 extern const float r_screenvertex3f[12];
285 extern const float r_d3dscreenvertex3f[12];
286 const float r_screenvertex3f[12] =
287 {
288         0, 0, 0,
289         1, 0, 0,
290         1, 1, 0,
291         0, 1, 0
292 };
293 const float r_d3dscreenvertex3f[12] =
294 {
295         0, 1, 0,
296         1, 1, 0,
297         1, 0, 0,
298         0, 0, 0
299 };
300
301 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
302 {
303         int i;
304         for (i = 0;i < verts;i++)
305         {
306                 out[0] = in[0] * r;
307                 out[1] = in[1] * g;
308                 out[2] = in[2] * b;
309                 out[3] = in[3];
310                 in += 4;
311                 out += 4;
312         }
313 }
314
315 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
316 {
317         int i;
318         for (i = 0;i < verts;i++)
319         {
320                 out[0] = r;
321                 out[1] = g;
322                 out[2] = b;
323                 out[3] = a;
324                 out += 4;
325         }
326 }
327
328 // FIXME: move this to client?
329 void FOG_clear(void)
330 {
331         if (gamemode == GAME_NEHAHRA)
332         {
333                 Cvar_Set("gl_fogenable", "0");
334                 Cvar_Set("gl_fogdensity", "0.2");
335                 Cvar_Set("gl_fogred", "0.3");
336                 Cvar_Set("gl_foggreen", "0.3");
337                 Cvar_Set("gl_fogblue", "0.3");
338         }
339         r_refdef.fog_density = 0;
340         r_refdef.fog_red = 0;
341         r_refdef.fog_green = 0;
342         r_refdef.fog_blue = 0;
343         r_refdef.fog_alpha = 1;
344         r_refdef.fog_start = 0;
345         r_refdef.fog_end = 16384;
346         r_refdef.fog_height = 1<<30;
347         r_refdef.fog_fadedepth = 128;
348         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
349 }
350
351 static void R_BuildBlankTextures(void)
352 {
353         unsigned char data[4];
354         data[2] = 128; // normal X
355         data[1] = 128; // normal Y
356         data[0] = 255; // normal Z
357         data[3] = 255; // height
358         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
359         data[0] = 255;
360         data[1] = 255;
361         data[2] = 255;
362         data[3] = 255;
363         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
364         data[0] = 128;
365         data[1] = 128;
366         data[2] = 128;
367         data[3] = 255;
368         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
369         data[0] = 0;
370         data[1] = 0;
371         data[2] = 0;
372         data[3] = 255;
373         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
374 }
375
376 static void R_BuildNoTexture(void)
377 {
378         int x, y;
379         unsigned char pix[16][16][4];
380         // this makes a light grey/dark grey checkerboard texture
381         for (y = 0;y < 16;y++)
382         {
383                 for (x = 0;x < 16;x++)
384                 {
385                         if ((y < 8) ^ (x < 8))
386                         {
387                                 pix[y][x][0] = 128;
388                                 pix[y][x][1] = 128;
389                                 pix[y][x][2] = 128;
390                                 pix[y][x][3] = 255;
391                         }
392                         else
393                         {
394                                 pix[y][x][0] = 64;
395                                 pix[y][x][1] = 64;
396                                 pix[y][x][2] = 64;
397                                 pix[y][x][3] = 255;
398                         }
399                 }
400         }
401         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
402 }
403
404 static void R_BuildWhiteCube(void)
405 {
406         unsigned char data[6*1*1*4];
407         memset(data, 255, sizeof(data));
408         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
409 }
410
411 static void R_BuildNormalizationCube(void)
412 {
413         int x, y, side;
414         vec3_t v;
415         vec_t s, t, intensity;
416 #define NORMSIZE 64
417         unsigned char *data;
418         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
419         for (side = 0;side < 6;side++)
420         {
421                 for (y = 0;y < NORMSIZE;y++)
422                 {
423                         for (x = 0;x < NORMSIZE;x++)
424                         {
425                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
426                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
427                                 switch(side)
428                                 {
429                                 default:
430                                 case 0:
431                                         v[0] = 1;
432                                         v[1] = -t;
433                                         v[2] = -s;
434                                         break;
435                                 case 1:
436                                         v[0] = -1;
437                                         v[1] = -t;
438                                         v[2] = s;
439                                         break;
440                                 case 2:
441                                         v[0] = s;
442                                         v[1] = 1;
443                                         v[2] = t;
444                                         break;
445                                 case 3:
446                                         v[0] = s;
447                                         v[1] = -1;
448                                         v[2] = -t;
449                                         break;
450                                 case 4:
451                                         v[0] = s;
452                                         v[1] = -t;
453                                         v[2] = 1;
454                                         break;
455                                 case 5:
456                                         v[0] = -s;
457                                         v[1] = -t;
458                                         v[2] = -1;
459                                         break;
460                                 }
461                                 intensity = 127.0f / sqrt(DotProduct(v, v));
462                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
463                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
464                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
465                                 data[((side*64+y)*64+x)*4+3] = 255;
466                         }
467                 }
468         }
469         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
470         Mem_Free(data);
471 }
472
473 static void R_BuildFogTexture(void)
474 {
475         int x, b;
476 #define FOGWIDTH 256
477         unsigned char data1[FOGWIDTH][4];
478         //unsigned char data2[FOGWIDTH][4];
479         double d, r, alpha;
480
481         r_refdef.fogmasktable_start = r_refdef.fog_start;
482         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
483         r_refdef.fogmasktable_range = r_refdef.fogrange;
484         r_refdef.fogmasktable_density = r_refdef.fog_density;
485
486         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
487         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
488         {
489                 d = (x * r - r_refdef.fogmasktable_start);
490                 if(developer_extra.integer)
491                         Con_DPrintf("%f ", d);
492                 d = max(0, d);
493                 if (r_fog_exp2.integer)
494                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
495                 else
496                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
497                 if(developer_extra.integer)
498                         Con_DPrintf(" : %f ", alpha);
499                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
500                 if(developer_extra.integer)
501                         Con_DPrintf(" = %f\n", alpha);
502                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
503         }
504
505         for (x = 0;x < FOGWIDTH;x++)
506         {
507                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
508                 data1[x][0] = b;
509                 data1[x][1] = b;
510                 data1[x][2] = b;
511                 data1[x][3] = 255;
512                 //data2[x][0] = 255 - b;
513                 //data2[x][1] = 255 - b;
514                 //data2[x][2] = 255 - b;
515                 //data2[x][3] = 255;
516         }
517         if (r_texture_fogattenuation)
518         {
519                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
520                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
521         }
522         else
523         {
524                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
525                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
526         }
527 }
528
529 static void R_BuildFogHeightTexture(void)
530 {
531         unsigned char *inpixels;
532         int size;
533         int x;
534         int y;
535         int j;
536         float c[4];
537         float f;
538         inpixels = NULL;
539         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
540         if (r_refdef.fogheighttexturename[0])
541                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
542         if (!inpixels)
543         {
544                 r_refdef.fog_height_tablesize = 0;
545                 if (r_texture_fogheighttexture)
546                         R_FreeTexture(r_texture_fogheighttexture);
547                 r_texture_fogheighttexture = NULL;
548                 if (r_refdef.fog_height_table2d)
549                         Mem_Free(r_refdef.fog_height_table2d);
550                 r_refdef.fog_height_table2d = NULL;
551                 if (r_refdef.fog_height_table1d)
552                         Mem_Free(r_refdef.fog_height_table1d);
553                 r_refdef.fog_height_table1d = NULL;
554                 return;
555         }
556         size = image_width;
557         r_refdef.fog_height_tablesize = size;
558         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
559         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
560         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
561         Mem_Free(inpixels);
562         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
563         // average fog color table accounting for every fog layer between a point
564         // and the camera.  (Note: attenuation is handled separately!)
565         for (y = 0;y < size;y++)
566         {
567                 for (x = 0;x < size;x++)
568                 {
569                         Vector4Clear(c);
570                         f = 0;
571                         if (x < y)
572                         {
573                                 for (j = x;j <= y;j++)
574                                 {
575                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
576                                         f++;
577                                 }
578                         }
579                         else
580                         {
581                                 for (j = x;j >= y;j--)
582                                 {
583                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
584                                         f++;
585                                 }
586                         }
587                         f = 1.0f / f;
588                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
589                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
590                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
591                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
592                 }
593         }
594         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
595 }
596
597 //=======================================================================================================================================================
598
599 static const char *builtinshaderstring =
600 #include "shader_glsl.h"
601 ;
602
603 const char *builtinhlslshaderstring =
604 #include "shader_hlsl.h"
605 ;
606
607 char *glslshaderstring = NULL;
608 char *hlslshaderstring = NULL;
609
610 //=======================================================================================================================================================
611
612 typedef struct shaderpermutationinfo_s
613 {
614         const char *pretext;
615         const char *name;
616 }
617 shaderpermutationinfo_t;
618
619 typedef struct shadermodeinfo_s
620 {
621         const char *vertexfilename;
622         const char *geometryfilename;
623         const char *fragmentfilename;
624         const char *pretext;
625         const char *name;
626 }
627 shadermodeinfo_t;
628
629 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
630 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
631 {
632         {"#define USEDIFFUSE\n", " diffuse"},
633         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
634         {"#define USEVIEWTINT\n", " viewtint"},
635         {"#define USECOLORMAPPING\n", " colormapping"},
636         {"#define USESATURATION\n", " saturation"},
637         {"#define USEFOGINSIDE\n", " foginside"},
638         {"#define USEFOGOUTSIDE\n", " fogoutside"},
639         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
640         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
641         {"#define USEGAMMARAMPS\n", " gammaramps"},
642         {"#define USECUBEFILTER\n", " cubefilter"},
643         {"#define USEGLOW\n", " glow"},
644         {"#define USEBLOOM\n", " bloom"},
645         {"#define USESPECULAR\n", " specular"},
646         {"#define USEPOSTPROCESSING\n", " postprocessing"},
647         {"#define USEREFLECTION\n", " reflection"},
648         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
649         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
650         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
651         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
652         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
653         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
654         {"#define USEALPHAKILL\n", " alphakill"},
655         {"#define USEREFLECTCUBE\n", " reflectcube"},
656         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
657         {"#define USEBOUNCEGRID\n", " bouncegrid"},
658         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
659         {"#define USETRIPPY\n", " trippy"},
660         {"#define USEDEPTHRGB\n", " depthrgb"},
661         {"#define USEALPHAGENVERTEX\n", "alphagenvertex"}
662 };
663
664 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
665 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
666 {
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
684         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
685 };
686
687 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
688 {
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
706         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
707 };
708
709 struct r_glsl_permutation_s;
710 typedef struct r_glsl_permutation_s
711 {
712         /// hash lookup data
713         struct r_glsl_permutation_s *hashnext;
714         unsigned int mode;
715         unsigned int permutation;
716
717         /// indicates if we have tried compiling this permutation already
718         qboolean compiled;
719         /// 0 if compilation failed
720         int program;
721         // texture units assigned to each detected uniform
722         int tex_Texture_First;
723         int tex_Texture_Second;
724         int tex_Texture_GammaRamps;
725         int tex_Texture_Normal;
726         int tex_Texture_Color;
727         int tex_Texture_Gloss;
728         int tex_Texture_Glow;
729         int tex_Texture_SecondaryNormal;
730         int tex_Texture_SecondaryColor;
731         int tex_Texture_SecondaryGloss;
732         int tex_Texture_SecondaryGlow;
733         int tex_Texture_Pants;
734         int tex_Texture_Shirt;
735         int tex_Texture_FogHeightTexture;
736         int tex_Texture_FogMask;
737         int tex_Texture_Lightmap;
738         int tex_Texture_Deluxemap;
739         int tex_Texture_Attenuation;
740         int tex_Texture_Cube;
741         int tex_Texture_Refraction;
742         int tex_Texture_Reflection;
743         int tex_Texture_ShadowMap2D;
744         int tex_Texture_CubeProjection;
745         int tex_Texture_ScreenNormalMap;
746         int tex_Texture_ScreenDiffuse;
747         int tex_Texture_ScreenSpecular;
748         int tex_Texture_ReflectMask;
749         int tex_Texture_ReflectCube;
750         int tex_Texture_BounceGrid;
751         /// locations of detected uniforms in program object, or -1 if not found
752         int loc_Texture_First;
753         int loc_Texture_Second;
754         int loc_Texture_GammaRamps;
755         int loc_Texture_Normal;
756         int loc_Texture_Color;
757         int loc_Texture_Gloss;
758         int loc_Texture_Glow;
759         int loc_Texture_SecondaryNormal;
760         int loc_Texture_SecondaryColor;
761         int loc_Texture_SecondaryGloss;
762         int loc_Texture_SecondaryGlow;
763         int loc_Texture_Pants;
764         int loc_Texture_Shirt;
765         int loc_Texture_FogHeightTexture;
766         int loc_Texture_FogMask;
767         int loc_Texture_Lightmap;
768         int loc_Texture_Deluxemap;
769         int loc_Texture_Attenuation;
770         int loc_Texture_Cube;
771         int loc_Texture_Refraction;
772         int loc_Texture_Reflection;
773         int loc_Texture_ShadowMap2D;
774         int loc_Texture_CubeProjection;
775         int loc_Texture_ScreenNormalMap;
776         int loc_Texture_ScreenDiffuse;
777         int loc_Texture_ScreenSpecular;
778         int loc_Texture_ReflectMask;
779         int loc_Texture_ReflectCube;
780         int loc_Texture_BounceGrid;
781         int loc_Alpha;
782         int loc_BloomBlur_Parameters;
783         int loc_ClientTime;
784         int loc_Color_Ambient;
785         int loc_Color_Diffuse;
786         int loc_Color_Specular;
787         int loc_Color_Glow;
788         int loc_Color_Pants;
789         int loc_Color_Shirt;
790         int loc_DeferredColor_Ambient;
791         int loc_DeferredColor_Diffuse;
792         int loc_DeferredColor_Specular;
793         int loc_DeferredMod_Diffuse;
794         int loc_DeferredMod_Specular;
795         int loc_DistortScaleRefractReflect;
796         int loc_EyePosition;
797         int loc_FogColor;
798         int loc_FogHeightFade;
799         int loc_FogPlane;
800         int loc_FogPlaneViewDist;
801         int loc_FogRangeRecip;
802         int loc_LightColor;
803         int loc_LightDir;
804         int loc_LightPosition;
805         int loc_OffsetMapping_ScaleSteps;
806         int loc_OffsetMapping_LodDistance;
807         int loc_OffsetMapping_Bias;
808         int loc_PixelSize;
809         int loc_ReflectColor;
810         int loc_ReflectFactor;
811         int loc_ReflectOffset;
812         int loc_RefractColor;
813         int loc_Saturation;
814         int loc_ScreenCenterRefractReflect;
815         int loc_ScreenScaleRefractReflect;
816         int loc_ScreenToDepth;
817         int loc_ShadowMap_Parameters;
818         int loc_ShadowMap_TextureScale;
819         int loc_SpecularPower;
820         int loc_UserVec1;
821         int loc_UserVec2;
822         int loc_UserVec3;
823         int loc_UserVec4;
824         int loc_ViewTintColor;
825         int loc_ViewToLight;
826         int loc_ModelToLight;
827         int loc_TexMatrix;
828         int loc_BackgroundTexMatrix;
829         int loc_ModelViewProjectionMatrix;
830         int loc_ModelViewMatrix;
831         int loc_PixelToScreenTexCoord;
832         int loc_ModelToReflectCube;
833         int loc_ShadowMapMatrix;
834         int loc_BloomColorSubtract;
835         int loc_NormalmapScrollBlend;
836         int loc_BounceGridMatrix;
837         int loc_BounceGridIntensity;
838 }
839 r_glsl_permutation_t;
840
841 #define SHADERPERMUTATION_HASHSIZE 256
842
843
844 // non-degradable "lightweight" shader parameters to keep the permutations simpler
845 // these can NOT degrade! only use for simple stuff
846 enum
847 {
848         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
849         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
850         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
851         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
852         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
853         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
854         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
855         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
856         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
857         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
858         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
859         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
860         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
861 };
862 #define SHADERSTATICPARMS_COUNT 13
863
864 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
865 static int shaderstaticparms_count = 0;
866
867 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
868 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
869
870 extern qboolean r_shadow_shadowmapsampler;
871 extern int r_shadow_shadowmappcf;
872 qboolean R_CompileShader_CheckStaticParms(void)
873 {
874         static int r_compileshader_staticparms_save[1];
875         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
876         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
877
878         // detect all
879         if (r_glsl_saturation_redcompensate.integer)
880                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
881         if (r_glsl_vertextextureblend_usebothalphas.integer)
882                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
883         if (r_shadow_glossexact.integer)
884                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
885         if (r_glsl_postprocess.integer)
886         {
887                 if (r_glsl_postprocess_uservec1_enable.integer)
888                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
889                 if (r_glsl_postprocess_uservec2_enable.integer)
890                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
891                 if (r_glsl_postprocess_uservec3_enable.integer)
892                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
893                 if (r_glsl_postprocess_uservec4_enable.integer)
894                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
895         }
896         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
897                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
898
899         if (r_shadow_shadowmapsampler)
900                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
901         if (r_shadow_shadowmappcf > 1)
902                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
903         else if (r_shadow_shadowmappcf)
904                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
905         if (r_celshading.integer)
906                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
907         if (r_celoutlines.integer)
908                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
909
910         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
911 }
912
913 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
914         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
915                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
916         else \
917                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
918 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
919 {
920         shaderstaticparms_count = 0;
921
922         // emit all
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
925         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
926         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
927         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
928         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
929         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
935         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
936 }
937
938 /// information about each possible shader permutation
939 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
940 /// currently selected permutation
941 r_glsl_permutation_t *r_glsl_permutation;
942 /// storage for permutations linked in the hash table
943 memexpandablearray_t r_glsl_permutationarray;
944
945 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
946 {
947         //unsigned int hashdepth = 0;
948         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
949         r_glsl_permutation_t *p;
950         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
951         {
952                 if (p->mode == mode && p->permutation == permutation)
953                 {
954                         //if (hashdepth > 10)
955                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
956                         return p;
957                 }
958                 //hashdepth++;
959         }
960         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
961         p->mode = mode;
962         p->permutation = permutation;
963         p->hashnext = r_glsl_permutationhash[mode][hashindex];
964         r_glsl_permutationhash[mode][hashindex] = p;
965         //if (hashdepth > 10)
966         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
967         return p;
968 }
969
970 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
971 {
972         char *shaderstring;
973         if (!filename || !filename[0])
974                 return NULL;
975         if (!strcmp(filename, "glsl/default.glsl"))
976         {
977                 if (!glslshaderstring)
978                 {
979                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
980                         if (glslshaderstring)
981                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
982                         else
983                                 glslshaderstring = (char *)builtinshaderstring;
984                 }
985                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
986                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
987                 return shaderstring;
988         }
989         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
990         if (shaderstring)
991         {
992                 if (printfromdisknotice)
993                         Con_DPrintf("from disk %s... ", filename);
994                 return shaderstring;
995         }
996         return shaderstring;
997 }
998
999 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1000 {
1001         int i;
1002         int sampler;
1003         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1004         char *vertexstring, *geometrystring, *fragmentstring;
1005         char permutationname[256];
1006         int vertstrings_count = 0;
1007         int geomstrings_count = 0;
1008         int fragstrings_count = 0;
1009         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1010         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1011         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1012
1013         if (p->compiled)
1014                 return;
1015         p->compiled = true;
1016         p->program = 0;
1017
1018         permutationname[0] = 0;
1019         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1020         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1021         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1022
1023         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1024
1025         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1026         if(vid.support.gl20shaders130)
1027         {
1028                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1029                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1030                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1031                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1032                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1033                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1034         }
1035
1036         // the first pretext is which type of shader to compile as
1037         // (later these will all be bound together as a program object)
1038         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1039         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1040         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1041
1042         // the second pretext is the mode (for example a light source)
1043         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1044         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1045         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1046         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1047
1048         // now add all the permutation pretexts
1049         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1050         {
1051                 if (permutation & (1<<i))
1052                 {
1053                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1054                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1055                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1056                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1057                 }
1058                 else
1059                 {
1060                         // keep line numbers correct
1061                         vertstrings_list[vertstrings_count++] = "\n";
1062                         geomstrings_list[geomstrings_count++] = "\n";
1063                         fragstrings_list[fragstrings_count++] = "\n";
1064                 }
1065         }
1066
1067         // add static parms
1068         R_CompileShader_AddStaticParms(mode, permutation);
1069         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1070         vertstrings_count += shaderstaticparms_count;
1071         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1072         geomstrings_count += shaderstaticparms_count;
1073         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1074         fragstrings_count += shaderstaticparms_count;
1075
1076         // now append the shader text itself
1077         vertstrings_list[vertstrings_count++] = vertexstring;
1078         geomstrings_list[geomstrings_count++] = geometrystring;
1079         fragstrings_list[fragstrings_count++] = fragmentstring;
1080
1081         // if any sources were NULL, clear the respective list
1082         if (!vertexstring)
1083                 vertstrings_count = 0;
1084         if (!geometrystring)
1085                 geomstrings_count = 0;
1086         if (!fragmentstring)
1087                 fragstrings_count = 0;
1088
1089         // compile the shader program
1090         if (vertstrings_count + geomstrings_count + fragstrings_count)
1091                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1092         if (p->program)
1093         {
1094                 CHECKGLERROR
1095                 qglUseProgram(p->program);CHECKGLERROR
1096                 // look up all the uniform variable names we care about, so we don't
1097                 // have to look them up every time we set them
1098
1099                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1100                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1101                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1102                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1103                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1104                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1105                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1106                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1107                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1108                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1109                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1110                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1111                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1112                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1113                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1114                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1115                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1116                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1117                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1118                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1119                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1120                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1121                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1122                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1123                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1124                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1125                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1126                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1127                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1128                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1129                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1130                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1131                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1132                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1133                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1134                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1135                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1136                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1137                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1138                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1139                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1140                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1141                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1142                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1143                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1144                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1145                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1146                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1147                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1148                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1149                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1150                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1151                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1152                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1153                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1154                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1155                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1156                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1157                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1158                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1159                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1160                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1161                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1162                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1163                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1164                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1165                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1166                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1167                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1168                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1169                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1170                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1171                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1172                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1173                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1174                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1175                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1176                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1177                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1178                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1179                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1180                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1181                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1182                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1183                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1184                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1185                 // initialize the samplers to refer to the texture units we use
1186                 p->tex_Texture_First = -1;
1187                 p->tex_Texture_Second = -1;
1188                 p->tex_Texture_GammaRamps = -1;
1189                 p->tex_Texture_Normal = -1;
1190                 p->tex_Texture_Color = -1;
1191                 p->tex_Texture_Gloss = -1;
1192                 p->tex_Texture_Glow = -1;
1193                 p->tex_Texture_SecondaryNormal = -1;
1194                 p->tex_Texture_SecondaryColor = -1;
1195                 p->tex_Texture_SecondaryGloss = -1;
1196                 p->tex_Texture_SecondaryGlow = -1;
1197                 p->tex_Texture_Pants = -1;
1198                 p->tex_Texture_Shirt = -1;
1199                 p->tex_Texture_FogHeightTexture = -1;
1200                 p->tex_Texture_FogMask = -1;
1201                 p->tex_Texture_Lightmap = -1;
1202                 p->tex_Texture_Deluxemap = -1;
1203                 p->tex_Texture_Attenuation = -1;
1204                 p->tex_Texture_Cube = -1;
1205                 p->tex_Texture_Refraction = -1;
1206                 p->tex_Texture_Reflection = -1;
1207                 p->tex_Texture_ShadowMap2D = -1;
1208                 p->tex_Texture_CubeProjection = -1;
1209                 p->tex_Texture_ScreenNormalMap = -1;
1210                 p->tex_Texture_ScreenDiffuse = -1;
1211                 p->tex_Texture_ScreenSpecular = -1;
1212                 p->tex_Texture_ReflectMask = -1;
1213                 p->tex_Texture_ReflectCube = -1;
1214                 p->tex_Texture_BounceGrid = -1;
1215                 sampler = 0;
1216                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1217                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1218                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1219                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1220                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1221                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1222                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1223                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1224                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1225                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1226                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1227                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1228                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1229                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1230                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1231                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1232                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1233                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1234                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1235                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1236                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1237                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1238                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1239                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1240                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1241                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1242                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1243                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1244                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1245                 CHECKGLERROR
1246                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1247         }
1248         else
1249                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1250
1251         // free the strings
1252         if (vertexstring)
1253                 Mem_Free(vertexstring);
1254         if (geometrystring)
1255                 Mem_Free(geometrystring);
1256         if (fragmentstring)
1257                 Mem_Free(fragmentstring);
1258 }
1259
1260 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1261 {
1262         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1263         if (r_glsl_permutation != perm)
1264         {
1265                 r_glsl_permutation = perm;
1266                 if (!r_glsl_permutation->program)
1267                 {
1268                         if (!r_glsl_permutation->compiled)
1269                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1270                         if (!r_glsl_permutation->program)
1271                         {
1272                                 // remove features until we find a valid permutation
1273                                 int i;
1274                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1275                                 {
1276                                         // reduce i more quickly whenever it would not remove any bits
1277                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1278                                         if (!(permutation & j))
1279                                                 continue;
1280                                         permutation -= j;
1281                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1282                                         if (!r_glsl_permutation->compiled)
1283                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1284                                         if (r_glsl_permutation->program)
1285                                                 break;
1286                                 }
1287                                 if (i >= SHADERPERMUTATION_COUNT)
1288                                 {
1289                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1290                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1291                                         qglUseProgram(0);CHECKGLERROR
1292                                         return; // no bit left to clear, entire mode is broken
1293                                 }
1294                         }
1295                 }
1296                 CHECKGLERROR
1297                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1298         }
1299         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1300         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1301         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1302 }
1303
1304 #ifdef SUPPORTD3D
1305
1306 #ifdef SUPPORTD3D
1307 #include <d3d9.h>
1308 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1309 extern D3DCAPS9 vid_d3d9caps;
1310 #endif
1311
1312 struct r_hlsl_permutation_s;
1313 typedef struct r_hlsl_permutation_s
1314 {
1315         /// hash lookup data
1316         struct r_hlsl_permutation_s *hashnext;
1317         unsigned int mode;
1318         unsigned int permutation;
1319
1320         /// indicates if we have tried compiling this permutation already
1321         qboolean compiled;
1322         /// NULL if compilation failed
1323         IDirect3DVertexShader9 *vertexshader;
1324         IDirect3DPixelShader9 *pixelshader;
1325 }
1326 r_hlsl_permutation_t;
1327
1328 typedef enum D3DVSREGISTER_e
1329 {
1330         D3DVSREGISTER_TexMatrix = 0, // float4x4
1331         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1332         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1333         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1334         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1335         D3DVSREGISTER_ModelToLight = 20, // float4x4
1336         D3DVSREGISTER_EyePosition = 24,
1337         D3DVSREGISTER_FogPlane = 25,
1338         D3DVSREGISTER_LightDir = 26,
1339         D3DVSREGISTER_LightPosition = 27,
1340 }
1341 D3DVSREGISTER_t;
1342
1343 typedef enum D3DPSREGISTER_e
1344 {
1345         D3DPSREGISTER_Alpha = 0,
1346         D3DPSREGISTER_BloomBlur_Parameters = 1,
1347         D3DPSREGISTER_ClientTime = 2,
1348         D3DPSREGISTER_Color_Ambient = 3,
1349         D3DPSREGISTER_Color_Diffuse = 4,
1350         D3DPSREGISTER_Color_Specular = 5,
1351         D3DPSREGISTER_Color_Glow = 6,
1352         D3DPSREGISTER_Color_Pants = 7,
1353         D3DPSREGISTER_Color_Shirt = 8,
1354         D3DPSREGISTER_DeferredColor_Ambient = 9,
1355         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1356         D3DPSREGISTER_DeferredColor_Specular = 11,
1357         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1358         D3DPSREGISTER_DeferredMod_Specular = 13,
1359         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1360         D3DPSREGISTER_EyePosition = 15, // unused
1361         D3DPSREGISTER_FogColor = 16,
1362         D3DPSREGISTER_FogHeightFade = 17,
1363         D3DPSREGISTER_FogPlane = 18,
1364         D3DPSREGISTER_FogPlaneViewDist = 19,
1365         D3DPSREGISTER_FogRangeRecip = 20,
1366         D3DPSREGISTER_LightColor = 21,
1367         D3DPSREGISTER_LightDir = 22, // unused
1368         D3DPSREGISTER_LightPosition = 23,
1369         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1370         D3DPSREGISTER_PixelSize = 25,
1371         D3DPSREGISTER_ReflectColor = 26,
1372         D3DPSREGISTER_ReflectFactor = 27,
1373         D3DPSREGISTER_ReflectOffset = 28,
1374         D3DPSREGISTER_RefractColor = 29,
1375         D3DPSREGISTER_Saturation = 30,
1376         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1377         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1378         D3DPSREGISTER_ScreenToDepth = 33,
1379         D3DPSREGISTER_ShadowMap_Parameters = 34,
1380         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1381         D3DPSREGISTER_SpecularPower = 36,
1382         D3DPSREGISTER_UserVec1 = 37,
1383         D3DPSREGISTER_UserVec2 = 38,
1384         D3DPSREGISTER_UserVec3 = 39,
1385         D3DPSREGISTER_UserVec4 = 40,
1386         D3DPSREGISTER_ViewTintColor = 41,
1387         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1388         D3DPSREGISTER_BloomColorSubtract = 43,
1389         D3DPSREGISTER_ViewToLight = 44, // float4x4
1390         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1391         D3DPSREGISTER_NormalmapScrollBlend = 52,
1392         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1393         D3DPSREGISTER_OffsetMapping_Bias = 54,
1394         // next at 54
1395 }
1396 D3DPSREGISTER_t;
1397
1398 /// information about each possible shader permutation
1399 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1400 /// currently selected permutation
1401 r_hlsl_permutation_t *r_hlsl_permutation;
1402 /// storage for permutations linked in the hash table
1403 memexpandablearray_t r_hlsl_permutationarray;
1404
1405 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1406 {
1407         //unsigned int hashdepth = 0;
1408         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1409         r_hlsl_permutation_t *p;
1410         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1411         {
1412                 if (p->mode == mode && p->permutation == permutation)
1413                 {
1414                         //if (hashdepth > 10)
1415                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1416                         return p;
1417                 }
1418                 //hashdepth++;
1419         }
1420         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1421         p->mode = mode;
1422         p->permutation = permutation;
1423         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1424         r_hlsl_permutationhash[mode][hashindex] = p;
1425         //if (hashdepth > 10)
1426         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1427         return p;
1428 }
1429
1430 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1431 {
1432         char *shaderstring;
1433         if (!filename || !filename[0])
1434                 return NULL;
1435         if (!strcmp(filename, "hlsl/default.hlsl"))
1436         {
1437                 if (!hlslshaderstring)
1438                 {
1439                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1440                         if (hlslshaderstring)
1441                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1442                         else
1443                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1444                 }
1445                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1446                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1447                 return shaderstring;
1448         }
1449         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1450         if (shaderstring)
1451         {
1452                 if (printfromdisknotice)
1453                         Con_DPrintf("from disk %s... ", filename);
1454                 return shaderstring;
1455         }
1456         return shaderstring;
1457 }
1458
1459 #include <d3dx9.h>
1460 //#include <d3dx9shader.h>
1461 //#include <d3dx9mesh.h>
1462
1463 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1464 {
1465         DWORD *vsbin = NULL;
1466         DWORD *psbin = NULL;
1467         fs_offset_t vsbinsize;
1468         fs_offset_t psbinsize;
1469 //      IDirect3DVertexShader9 *vs = NULL;
1470 //      IDirect3DPixelShader9 *ps = NULL;
1471         ID3DXBuffer *vslog = NULL;
1472         ID3DXBuffer *vsbuffer = NULL;
1473         ID3DXConstantTable *vsconstanttable = NULL;
1474         ID3DXBuffer *pslog = NULL;
1475         ID3DXBuffer *psbuffer = NULL;
1476         ID3DXConstantTable *psconstanttable = NULL;
1477         int vsresult = 0;
1478         int psresult = 0;
1479         char temp[MAX_INPUTLINE];
1480         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1481         char vabuf[1024];
1482         qboolean debugshader = gl_paranoid.integer != 0;
1483         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1484         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1485         if (!debugshader)
1486         {
1487                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1488                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1489         }
1490         if ((!vsbin && vertstring) || (!psbin && fragstring))
1491         {
1492                 const char* dllnames_d3dx9 [] =
1493                 {
1494                         "d3dx9_43.dll",
1495                         "d3dx9_42.dll",
1496                         "d3dx9_41.dll",
1497                         "d3dx9_40.dll",
1498                         "d3dx9_39.dll",
1499                         "d3dx9_38.dll",
1500                         "d3dx9_37.dll",
1501                         "d3dx9_36.dll",
1502                         "d3dx9_35.dll",
1503                         "d3dx9_34.dll",
1504                         "d3dx9_33.dll",
1505                         "d3dx9_32.dll",
1506                         "d3dx9_31.dll",
1507                         "d3dx9_30.dll",
1508                         "d3dx9_29.dll",
1509                         "d3dx9_28.dll",
1510                         "d3dx9_27.dll",
1511                         "d3dx9_26.dll",
1512                         "d3dx9_25.dll",
1513                         "d3dx9_24.dll",
1514                         NULL
1515                 };
1516                 dllhandle_t d3dx9_dll = NULL;
1517                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1518                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1519                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1520                 dllfunction_t d3dx9_dllfuncs[] =
1521                 {
1522                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1523                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1524                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1525                         {NULL, NULL}
1526                 };
1527                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1528                 {
1529                         DWORD shaderflags = 0;
1530                         if (debugshader)
1531                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1532                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1533                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1534                         if (vertstring && vertstring[0])
1535                         {
1536                                 if (debugshader)
1537                                 {
1538 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1539 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1540                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1541                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1542                                 }
1543                                 else
1544                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1545                                 if (vsbuffer)
1546                                 {
1547                                         vsbinsize = vsbuffer->GetBufferSize();
1548                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1549                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1550                                         vsbuffer->Release();
1551                                 }
1552                                 if (vslog)
1553                                 {
1554                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1555                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1556                                         vslog->Release();
1557                                 }
1558                         }
1559                         if (fragstring && fragstring[0])
1560                         {
1561                                 if (debugshader)
1562                                 {
1563 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1564 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1565                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1566                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1567                                 }
1568                                 else
1569                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1570                                 if (psbuffer)
1571                                 {
1572                                         psbinsize = psbuffer->GetBufferSize();
1573                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1574                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1575                                         psbuffer->Release();
1576                                 }
1577                                 if (pslog)
1578                                 {
1579                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1580                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1581                                         pslog->Release();
1582                                 }
1583                         }
1584                         Sys_UnloadLibrary(&d3dx9_dll);
1585                 }
1586                 else
1587                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1588         }
1589         if (vsbin && psbin)
1590         {
1591                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1592                 if (FAILED(vsresult))
1593                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1594                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1595                 if (FAILED(psresult))
1596                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1597         }
1598         // free the shader data
1599         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1600         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1601 }
1602
1603 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1604 {
1605         int i;
1606         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1607         int vertstring_length = 0;
1608         int geomstring_length = 0;
1609         int fragstring_length = 0;
1610         char *t;
1611         char *vertexstring, *geometrystring, *fragmentstring;
1612         char *vertstring, *geomstring, *fragstring;
1613         char permutationname[256];
1614         char cachename[256];
1615         int vertstrings_count = 0;
1616         int geomstrings_count = 0;
1617         int fragstrings_count = 0;
1618         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1619         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1620         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1621
1622         if (p->compiled)
1623                 return;
1624         p->compiled = true;
1625         p->vertexshader = NULL;
1626         p->pixelshader = NULL;
1627
1628         permutationname[0] = 0;
1629         cachename[0] = 0;
1630         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1631         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1632         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1633
1634         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1635         strlcat(cachename, "hlsl/", sizeof(cachename));
1636
1637         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1638         vertstrings_count = 0;
1639         geomstrings_count = 0;
1640         fragstrings_count = 0;
1641         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1642         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1643         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1644
1645         // the first pretext is which type of shader to compile as
1646         // (later these will all be bound together as a program object)
1647         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1648         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1649         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1650
1651         // the second pretext is the mode (for example a light source)
1652         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1653         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1654         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1655         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1656         strlcat(cachename, modeinfo->name, sizeof(cachename));
1657
1658         // now add all the permutation pretexts
1659         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1660         {
1661                 if (permutation & (1<<i))
1662                 {
1663                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1664                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1665                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1666                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1667                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1668                 }
1669                 else
1670                 {
1671                         // keep line numbers correct
1672                         vertstrings_list[vertstrings_count++] = "\n";
1673                         geomstrings_list[geomstrings_count++] = "\n";
1674                         fragstrings_list[fragstrings_count++] = "\n";
1675                 }
1676         }
1677
1678         // add static parms
1679         R_CompileShader_AddStaticParms(mode, permutation);
1680         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1681         vertstrings_count += shaderstaticparms_count;
1682         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1683         geomstrings_count += shaderstaticparms_count;
1684         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1685         fragstrings_count += shaderstaticparms_count;
1686
1687         // replace spaces in the cachename with _ characters
1688         for (i = 0;cachename[i];i++)
1689                 if (cachename[i] == ' ')
1690                         cachename[i] = '_';
1691
1692         // now append the shader text itself
1693         vertstrings_list[vertstrings_count++] = vertexstring;
1694         geomstrings_list[geomstrings_count++] = geometrystring;
1695         fragstrings_list[fragstrings_count++] = fragmentstring;
1696
1697         // if any sources were NULL, clear the respective list
1698         if (!vertexstring)
1699                 vertstrings_count = 0;
1700         if (!geometrystring)
1701                 geomstrings_count = 0;
1702         if (!fragmentstring)
1703                 fragstrings_count = 0;
1704
1705         vertstring_length = 0;
1706         for (i = 0;i < vertstrings_count;i++)
1707                 vertstring_length += strlen(vertstrings_list[i]);
1708         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1709         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1710                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1711
1712         geomstring_length = 0;
1713         for (i = 0;i < geomstrings_count;i++)
1714                 geomstring_length += strlen(geomstrings_list[i]);
1715         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1716         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1717                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1718
1719         fragstring_length = 0;
1720         for (i = 0;i < fragstrings_count;i++)
1721                 fragstring_length += strlen(fragstrings_list[i]);
1722         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1723         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1724                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1725
1726         // try to load the cached shader, or generate one
1727         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1728
1729         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1730                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1731         else
1732                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1733
1734         // free the strings
1735         if (vertstring)
1736                 Mem_Free(vertstring);
1737         if (geomstring)
1738                 Mem_Free(geomstring);
1739         if (fragstring)
1740                 Mem_Free(fragstring);
1741         if (vertexstring)
1742                 Mem_Free(vertexstring);
1743         if (geometrystring)
1744                 Mem_Free(geometrystring);
1745         if (fragmentstring)
1746                 Mem_Free(fragmentstring);
1747 }
1748
1749 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1750 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1751 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);}
1752 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);}
1753 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);}
1754 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);}
1755
1756 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1757 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1758 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);}
1759 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);}
1760 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);}
1761 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);}
1762
1763 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1764 {
1765         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1766         if (r_hlsl_permutation != perm)
1767         {
1768                 r_hlsl_permutation = perm;
1769                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1770                 {
1771                         if (!r_hlsl_permutation->compiled)
1772                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1773                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1774                         {
1775                                 // remove features until we find a valid permutation
1776                                 int i;
1777                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1778                                 {
1779                                         // reduce i more quickly whenever it would not remove any bits
1780                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1781                                         if (!(permutation & j))
1782                                                 continue;
1783                                         permutation -= j;
1784                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1785                                         if (!r_hlsl_permutation->compiled)
1786                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1787                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1788                                                 break;
1789                                 }
1790                                 if (i >= SHADERPERMUTATION_COUNT)
1791                                 {
1792                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1793                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1794                                         return; // no bit left to clear, entire mode is broken
1795                                 }
1796                         }
1797                 }
1798                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1799                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1800         }
1801         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1802         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1803         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1804 }
1805 #endif
1806
1807 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1808 {
1809         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1810         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1811         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1812         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1813 }
1814
1815 void R_GLSL_Restart_f(void)
1816 {
1817         unsigned int i, limit;
1818         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1819                 Mem_Free(glslshaderstring);
1820         glslshaderstring = NULL;
1821         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1822                 Mem_Free(hlslshaderstring);
1823         hlslshaderstring = NULL;
1824         switch(vid.renderpath)
1825         {
1826         case RENDERPATH_D3D9:
1827 #ifdef SUPPORTD3D
1828                 {
1829                         r_hlsl_permutation_t *p;
1830                         r_hlsl_permutation = NULL;
1831                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1832                         for (i = 0;i < limit;i++)
1833                         {
1834                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1835                                 {
1836                                         if (p->vertexshader)
1837                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1838                                         if (p->pixelshader)
1839                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1840                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1841                                 }
1842                         }
1843                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1844                 }
1845 #endif
1846                 break;
1847         case RENDERPATH_D3D10:
1848                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1849                 break;
1850         case RENDERPATH_D3D11:
1851                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1852                 break;
1853         case RENDERPATH_GL20:
1854         case RENDERPATH_GLES2:
1855                 {
1856                         r_glsl_permutation_t *p;
1857                         r_glsl_permutation = NULL;
1858                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1859                         for (i = 0;i < limit;i++)
1860                         {
1861                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1862                                 {
1863                                         GL_Backend_FreeProgram(p->program);
1864                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1865                                 }
1866                         }
1867                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1868                 }
1869                 break;
1870         case RENDERPATH_GL11:
1871         case RENDERPATH_GL13:
1872         case RENDERPATH_GLES1:
1873                 break;
1874         case RENDERPATH_SOFT:
1875                 break;
1876         }
1877 }
1878
1879 static void R_GLSL_DumpShader_f(void)
1880 {
1881         int i;
1882         qfile_t *file;
1883
1884         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1885         if (file)
1886         {
1887                 FS_Print(file, "/* The engine may define the following macros:\n");
1888                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1889                 for (i = 0;i < SHADERMODE_COUNT;i++)
1890                         FS_Print(file, glslshadermodeinfo[i].pretext);
1891                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1892                         FS_Print(file, shaderpermutationinfo[i].pretext);
1893                 FS_Print(file, "*/\n");
1894                 FS_Print(file, builtinshaderstring);
1895                 FS_Close(file);
1896                 Con_Printf("glsl/default.glsl written\n");
1897         }
1898         else
1899                 Con_Printf("failed to write to glsl/default.glsl\n");
1900
1901         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1902         if (file)
1903         {
1904                 FS_Print(file, "/* The engine may define the following macros:\n");
1905                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1906                 for (i = 0;i < SHADERMODE_COUNT;i++)
1907                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1908                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1909                         FS_Print(file, shaderpermutationinfo[i].pretext);
1910                 FS_Print(file, "*/\n");
1911                 FS_Print(file, builtinhlslshaderstring);
1912                 FS_Close(file);
1913                 Con_Printf("hlsl/default.hlsl written\n");
1914         }
1915         else
1916                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1917 }
1918
1919 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1920 {
1921         unsigned int permutation = 0;
1922         if (r_trippy.integer && !notrippy)
1923                 permutation |= SHADERPERMUTATION_TRIPPY;
1924         permutation |= SHADERPERMUTATION_VIEWTINT;
1925         if (first)
1926                 permutation |= SHADERPERMUTATION_DIFFUSE;
1927         if (second)
1928                 permutation |= SHADERPERMUTATION_SPECULAR;
1929         if (texturemode == GL_MODULATE)
1930                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1931         else if (texturemode == GL_ADD)
1932                 permutation |= SHADERPERMUTATION_GLOW;
1933         else if (texturemode == GL_DECAL)
1934                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1935         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1936                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1937         if (suppresstexalpha)
1938                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1939         if (!second)
1940                 texturemode = GL_MODULATE;
1941         if (vid.allowalphatocoverage)
1942                 GL_AlphaToCoverage(false);
1943         switch (vid.renderpath)
1944         {
1945         case RENDERPATH_D3D9:
1946 #ifdef SUPPORTD3D
1947                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1948                 R_Mesh_TexBind(GL20TU_FIRST , first );
1949                 R_Mesh_TexBind(GL20TU_SECOND, second);
1950                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1951                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1952 #endif
1953                 break;
1954         case RENDERPATH_D3D10:
1955                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1956                 break;
1957         case RENDERPATH_D3D11:
1958                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1959                 break;
1960         case RENDERPATH_GL20:
1961         case RENDERPATH_GLES2:
1962                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1963                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1964                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1965                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1966                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1967                 break;
1968         case RENDERPATH_GL13:
1969         case RENDERPATH_GLES1:
1970                 R_Mesh_TexBind(0, first );
1971                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1972                 R_Mesh_TexBind(1, second);
1973                 if (second)
1974                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1975                 break;
1976         case RENDERPATH_GL11:
1977                 R_Mesh_TexBind(0, first );
1978                 break;
1979         case RENDERPATH_SOFT:
1980                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1981                 R_Mesh_TexBind(GL20TU_FIRST , first );
1982                 R_Mesh_TexBind(GL20TU_SECOND, second);
1983                 break;
1984         }
1985 }
1986
1987 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1988 {
1989         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1990 }
1991
1992 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1993 {
1994         unsigned int permutation = 0;
1995         if (r_trippy.integer && !notrippy)
1996                 permutation |= SHADERPERMUTATION_TRIPPY;
1997         if (depthrgb)
1998                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1999         if (vid.allowalphatocoverage)
2000                 GL_AlphaToCoverage(false);
2001         switch (vid.renderpath)
2002         {
2003         case RENDERPATH_D3D9:
2004 #ifdef SUPPORTD3D
2005                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2006 #endif
2007                 break;
2008         case RENDERPATH_D3D10:
2009                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2010                 break;
2011         case RENDERPATH_D3D11:
2012                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2013                 break;
2014         case RENDERPATH_GL20:
2015         case RENDERPATH_GLES2:
2016                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2017                 break;
2018         case RENDERPATH_GL13:
2019         case RENDERPATH_GLES1:
2020                 R_Mesh_TexBind(0, 0);
2021                 R_Mesh_TexBind(1, 0);
2022                 break;
2023         case RENDERPATH_GL11:
2024                 R_Mesh_TexBind(0, 0);
2025                 break;
2026         case RENDERPATH_SOFT:
2027                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2028                 break;
2029         }
2030 }
2031
2032 void R_SetupShader_ShowDepth(qboolean notrippy)
2033 {
2034         int permutation = 0;
2035         if (r_trippy.integer && !notrippy)
2036                 permutation |= SHADERPERMUTATION_TRIPPY;
2037         if (vid.allowalphatocoverage)
2038                 GL_AlphaToCoverage(false);
2039         switch (vid.renderpath)
2040         {
2041         case RENDERPATH_D3D9:
2042 #ifdef SUPPORTHLSL
2043                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2044 #endif
2045                 break;
2046         case RENDERPATH_D3D10:
2047                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2048                 break;
2049         case RENDERPATH_D3D11:
2050                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2051                 break;
2052         case RENDERPATH_GL20:
2053         case RENDERPATH_GLES2:
2054                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2055                 break;
2056         case RENDERPATH_GL13:
2057         case RENDERPATH_GLES1:
2058                 break;
2059         case RENDERPATH_GL11:
2060                 break;
2061         case RENDERPATH_SOFT:
2062                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2063                 break;
2064         }
2065 }
2066
2067 extern qboolean r_shadow_usingdeferredprepass;
2068 extern rtexture_t *r_shadow_attenuationgradienttexture;
2069 extern rtexture_t *r_shadow_attenuation2dtexture;
2070 extern rtexture_t *r_shadow_attenuation3dtexture;
2071 extern qboolean r_shadow_usingshadowmap2d;
2072 extern qboolean r_shadow_usingshadowmaportho;
2073 extern float r_shadow_shadowmap_texturescale[2];
2074 extern float r_shadow_shadowmap_parameters[4];
2075 extern qboolean r_shadow_shadowmapvsdct;
2076 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2077 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2078 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2079 extern matrix4x4_t r_shadow_shadowmapmatrix;
2080 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2081 extern int r_shadow_prepass_width;
2082 extern int r_shadow_prepass_height;
2083 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2084 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2085 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2086 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2087
2088 #define BLENDFUNC_ALLOWS_COLORMOD      1
2089 #define BLENDFUNC_ALLOWS_FOG           2
2090 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2091 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2092 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2093 static int R_BlendFuncFlags(int src, int dst)
2094 {
2095         int r = 0;
2096
2097         // a blendfunc allows colormod if:
2098         // a) it can never keep the destination pixel invariant, or
2099         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2100         // this is to prevent unintended side effects from colormod
2101
2102         // a blendfunc allows fog if:
2103         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2104         // this is to prevent unintended side effects from fog
2105
2106         // these checks are the output of fogeval.pl
2107
2108         r |= BLENDFUNC_ALLOWS_COLORMOD;
2109         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2110         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2111         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2112         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2113         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2114         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2115         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2116         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2117         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2118         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2119         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2120         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2121         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2122         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2123         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2124         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2125         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2126         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2127         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2128         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2129         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2130
2131         return r;
2132 }
2133
2134 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)
2135 {
2136         // select a permutation of the lighting shader appropriate to this
2137         // combination of texture, entity, light source, and fogging, only use the
2138         // minimum features necessary to avoid wasting rendering time in the
2139         // fragment shader on features that are not being used
2140         unsigned int permutation = 0;
2141         unsigned int mode = 0;
2142         int blendfuncflags;
2143         static float dummy_colormod[3] = {1, 1, 1};
2144         float *colormod = rsurface.colormod;
2145         float m16f[16];
2146         matrix4x4_t tempmatrix;
2147         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2148         if (r_trippy.integer && !notrippy)
2149                 permutation |= SHADERPERMUTATION_TRIPPY;
2150         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2151                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2152         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2153                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2154         if (rsurfacepass == RSURFPASS_BACKGROUND)
2155         {
2156                 // distorted background
2157                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2158                 {
2159                         mode = SHADERMODE_WATER;
2160                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2161                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2162                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2163                         {
2164                                 // this is the right thing to do for wateralpha
2165                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2166                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2167                         }
2168                         else
2169                         {
2170                                 // this is the right thing to do for entity alpha
2171                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2172                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2173                         }
2174                 }
2175                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2176                 {
2177                         mode = SHADERMODE_REFRACTION;
2178                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2179                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2180                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2181                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2182                 }
2183                 else
2184                 {
2185                         mode = SHADERMODE_GENERIC;
2186                         permutation |= SHADERPERMUTATION_DIFFUSE | SHADERPERMUTATION_ALPHAKILL;
2187                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2188                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2189                 }
2190                 if (vid.allowalphatocoverage)
2191                         GL_AlphaToCoverage(false);
2192         }
2193         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2194         {
2195                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2196                 {
2197                         switch(rsurface.texture->offsetmapping)
2198                         {
2199                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2200                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2201                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2202                         case OFFSETMAPPING_OFF: break;
2203                         }
2204                 }
2205                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2206                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2207                 // normalmap (deferred prepass), may use alpha test on diffuse
2208                 mode = SHADERMODE_DEFERREDGEOMETRY;
2209                 GL_BlendFunc(GL_ONE, GL_ZERO);
2210                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2211                 if (vid.allowalphatocoverage)
2212                         GL_AlphaToCoverage(false);
2213         }
2214         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2215         {
2216                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2217                 {
2218                         switch(rsurface.texture->offsetmapping)
2219                         {
2220                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2221                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2222                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2223                         case OFFSETMAPPING_OFF: break;
2224                         }
2225                 }
2226                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2227                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2228                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2229                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2230                 // light source
2231                 mode = SHADERMODE_LIGHTSOURCE;
2232                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2233                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2234                 if (diffusescale > 0)
2235                         permutation |= SHADERPERMUTATION_DIFFUSE;
2236                 if (specularscale > 0)
2237                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2238                 if (r_refdef.fogenabled)
2239                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2240                 if (rsurface.texture->colormapping)
2241                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2242                 if (r_shadow_usingshadowmap2d)
2243                 {
2244                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2245                         if(r_shadow_shadowmapvsdct)
2246                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2247
2248                         if (r_shadow_shadowmap2ddepthbuffer)
2249                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2250                 }
2251                 if (rsurface.texture->reflectmasktexture)
2252                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2253                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2254                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2255                 if (vid.allowalphatocoverage)
2256                         GL_AlphaToCoverage(false);
2257         }
2258         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2259         {
2260                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2261                 {
2262                         switch(rsurface.texture->offsetmapping)
2263                         {
2264                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2265                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2266                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2267                         case OFFSETMAPPING_OFF: break;
2268                         }
2269                 }
2270                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2271                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2272                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2273                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2274                 // unshaded geometry (fullbright or ambient model lighting)
2275                 mode = SHADERMODE_FLATCOLOR;
2276                 ambientscale = diffusescale = specularscale = 0;
2277                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2278                         permutation |= SHADERPERMUTATION_GLOW;
2279                 if (r_refdef.fogenabled)
2280                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2281                 if (rsurface.texture->colormapping)
2282                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2283                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2284                 {
2285                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2286                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2287
2288                         if (r_shadow_shadowmap2ddepthbuffer)
2289                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2290                 }
2291                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2292                         permutation |= SHADERPERMUTATION_REFLECTION;
2293                 if (rsurface.texture->reflectmasktexture)
2294                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2295                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2296                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2297                 // when using alphatocoverage, we don't need alphakill
2298                 if (vid.allowalphatocoverage)
2299                 {
2300                         if (r_transparent_alphatocoverage.integer)
2301                         {
2302                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2303                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2304                         }
2305                         else
2306                                 GL_AlphaToCoverage(false);
2307                 }
2308         }
2309         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2310         {
2311                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2312                 {
2313                         switch(rsurface.texture->offsetmapping)
2314                         {
2315                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2316                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2317                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2318                         case OFFSETMAPPING_OFF: break;
2319                         }
2320                 }
2321                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2322                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2323                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2324                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2325                 // directional model lighting
2326                 mode = SHADERMODE_LIGHTDIRECTION;
2327                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2328                         permutation |= SHADERPERMUTATION_GLOW;
2329                 permutation |= SHADERPERMUTATION_DIFFUSE;
2330                 if (specularscale > 0)
2331                         permutation |= SHADERPERMUTATION_SPECULAR;
2332                 if (r_refdef.fogenabled)
2333                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2334                 if (rsurface.texture->colormapping)
2335                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2336                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2337                 {
2338                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2339                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2340
2341                         if (r_shadow_shadowmap2ddepthbuffer)
2342                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2343                 }
2344                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2345                         permutation |= SHADERPERMUTATION_REFLECTION;
2346                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2347                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2348                 if (rsurface.texture->reflectmasktexture)
2349                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2350                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2351                 {
2352                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2353                         if (r_shadow_bouncegriddirectional)
2354                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2355                 }
2356                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2357                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2358                 // when using alphatocoverage, we don't need alphakill
2359                 if (vid.allowalphatocoverage)
2360                 {
2361                         if (r_transparent_alphatocoverage.integer)
2362                         {
2363                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2364                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2365                         }
2366                         else
2367                                 GL_AlphaToCoverage(false);
2368                 }
2369         }
2370         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2371         {
2372                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2373                 {
2374                         switch(rsurface.texture->offsetmapping)
2375                         {
2376                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2377                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2378                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2379                         case OFFSETMAPPING_OFF: break;
2380                         }
2381                 }
2382                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2383                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2384                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2385                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2386                 // ambient model lighting
2387                 mode = SHADERMODE_LIGHTDIRECTION;
2388                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2389                         permutation |= SHADERPERMUTATION_GLOW;
2390                 if (r_refdef.fogenabled)
2391                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2392                 if (rsurface.texture->colormapping)
2393                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2394                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2395                 {
2396                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2397                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2398
2399                         if (r_shadow_shadowmap2ddepthbuffer)
2400                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2401                 }
2402                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2403                         permutation |= SHADERPERMUTATION_REFLECTION;
2404                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2405                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2406                 if (rsurface.texture->reflectmasktexture)
2407                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2408                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2409                 {
2410                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2411                         if (r_shadow_bouncegriddirectional)
2412                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2413                 }
2414                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2415                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2416                 // when using alphatocoverage, we don't need alphakill
2417                 if (vid.allowalphatocoverage)
2418                 {
2419                         if (r_transparent_alphatocoverage.integer)
2420                         {
2421                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2422                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2423                         }
2424                         else
2425                                 GL_AlphaToCoverage(false);
2426                 }
2427         }
2428         else
2429         {
2430                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2431                 {
2432                         switch(rsurface.texture->offsetmapping)
2433                         {
2434                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2435                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2436                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2437                         case OFFSETMAPPING_OFF: break;
2438                         }
2439                 }
2440                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2441                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2442                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2443                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2444                 // lightmapped wall
2445                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2446                         permutation |= SHADERPERMUTATION_GLOW;
2447                 if (r_refdef.fogenabled)
2448                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2449                 if (rsurface.texture->colormapping)
2450                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2451                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2452                 {
2453                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2454                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2455
2456                         if (r_shadow_shadowmap2ddepthbuffer)
2457                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2458                 }
2459                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2460                         permutation |= SHADERPERMUTATION_REFLECTION;
2461                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2462                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2463                 if (rsurface.texture->reflectmasktexture)
2464                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2465                 if (FAKELIGHT_ENABLED)
2466                 {
2467                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2468                         mode = SHADERMODE_FAKELIGHT;
2469                         permutation |= SHADERPERMUTATION_DIFFUSE;
2470                         if (specularscale > 0)
2471                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2472                 }
2473                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2474                 {
2475                         // deluxemapping (light direction texture)
2476                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2477                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2478                         else
2479                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2480                         permutation |= SHADERPERMUTATION_DIFFUSE;
2481                         if (specularscale > 0)
2482                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2483                 }
2484                 else if (r_glsl_deluxemapping.integer >= 2)
2485                 {
2486                         // fake deluxemapping (uniform light direction in tangentspace)
2487                         if (rsurface.uselightmaptexture)
2488                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2489                         else
2490                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2491                         permutation |= SHADERPERMUTATION_DIFFUSE;
2492                         if (specularscale > 0)
2493                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2494                 }
2495                 else if (rsurface.uselightmaptexture)
2496                 {
2497                         // ordinary lightmapping (q1bsp, q3bsp)
2498                         mode = SHADERMODE_LIGHTMAP;
2499                 }
2500                 else
2501                 {
2502                         // ordinary vertex coloring (q3bsp)
2503                         mode = SHADERMODE_VERTEXCOLOR;
2504                 }
2505                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2506                 {
2507                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2508                         if (r_shadow_bouncegriddirectional)
2509                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2510                 }
2511                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2512                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2513                 // when using alphatocoverage, we don't need alphakill
2514                 if (vid.allowalphatocoverage)
2515                 {
2516                         if (r_transparent_alphatocoverage.integer)
2517                         {
2518                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2519                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2520                         }
2521                         else
2522                                 GL_AlphaToCoverage(false);
2523                 }
2524         }
2525         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2526                 colormod = dummy_colormod;
2527         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2528                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2529         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2530                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2531         switch(vid.renderpath)
2532         {
2533         case RENDERPATH_D3D9:
2534 #ifdef SUPPORTD3D
2535                 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), texturenumsurfaces, texturesurfacelist);
2536                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2537                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2538                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2539                 if (mode == SHADERMODE_LIGHTSOURCE)
2540                 {
2541                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2542                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2543                 }
2544                 else
2545                 {
2546                         if (mode == SHADERMODE_LIGHTDIRECTION)
2547                         {
2548                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2549                         }
2550                 }
2551                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2552                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2553                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2554                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2555                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2556
2557                 if (mode == SHADERMODE_LIGHTSOURCE)
2558                 {
2559                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2560                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2561                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2562                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2563                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2564
2565                         // additive passes are only darkened by fog, not tinted
2566                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2567                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2568                 }
2569                 else
2570                 {
2571                         if (mode == SHADERMODE_FLATCOLOR)
2572                         {
2573                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2574                         }
2575                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2576                         {
2577                                 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]);
2578                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2579                                 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);
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2581                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2582                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2583                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2584                         }
2585                         else
2586                         {
2587                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2588                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2589                                 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);
2590                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2591                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2592                         }
2593                         // additive passes are only darkened by fog, not tinted
2594                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2595                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2596                         else
2597                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2598                         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);
2599                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2600                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2601                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2602                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2603                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2604                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2605                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2606                         if (mode == SHADERMODE_WATER)
2607                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2608                 }
2609                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2610                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2611                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2612                 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));
2613                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2614                 if (rsurface.texture->pantstexture)
2615                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2616                 else
2617                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2618                 if (rsurface.texture->shirttexture)
2619                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2620                 else
2621                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2622                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2623                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2624                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2625                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2626                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2627                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2628                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2629                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2630                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2631                         );
2632                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2633                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2634                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2635                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2636
2637                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2638                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2639                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2640                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2641                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2642                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2643                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2644                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2645                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2646                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2647                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2648                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2649                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2650                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2651                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2652                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2653                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2654                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2655                 {
2656                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2657                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2658                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2659                 }
2660                 else
2661                 {
2662                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2663                 }
2664 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2665                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2666                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2667                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2668                 {
2669                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2670                         if (rsurface.rtlight)
2671                         {
2672                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2673                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2674                         }
2675                 }
2676 #endif
2677                 break;
2678         case RENDERPATH_D3D10:
2679                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2680                 break;
2681         case RENDERPATH_D3D11:
2682                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2683                 break;
2684         case RENDERPATH_GL20:
2685         case RENDERPATH_GLES2:
2686                 if (!vid.useinterleavedarrays)
2687                 {
2688                         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), texturenumsurfaces, texturesurfacelist);
2689                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2690                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2691                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2692                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2693                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2694                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2695                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2696                 }
2697                 else
2698                 {
2699                         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), texturenumsurfaces, texturesurfacelist);
2700                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2701                 }
2702                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2703                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2704                 if (mode == SHADERMODE_LIGHTSOURCE)
2705                 {
2706                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2707                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2708                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2709                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2710                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2711                         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);
2712         
2713                         // additive passes are only darkened by fog, not tinted
2714                         if (r_glsl_permutation->loc_FogColor >= 0)
2715                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2716                         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);
2717                 }
2718                 else
2719                 {
2720                         if (mode == SHADERMODE_FLATCOLOR)
2721                         {
2722                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2723                         }
2724                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2725                         {
2726                                 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]);
2727                                 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]);
2728                                 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);
2729                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2730                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2731                                 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]);
2732                                 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]);
2733                         }
2734                         else
2735                         {
2736                                 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]);
2737                                 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]);
2738                                 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);
2739                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2740                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2741                         }
2742                         // additive passes are only darkened by fog, not tinted
2743                         if (r_glsl_permutation->loc_FogColor >= 0)
2744                         {
2745                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2746                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2747                                 else
2748                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2749                         }
2750                         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);
2751                         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]);
2752                         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]);
2753                         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]);
2754                         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]);
2755                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2756                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2757                         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);
2758                         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]);
2759                 }
2760                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2761                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2762                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2763                 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]);
2764                 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]);
2765
2766                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2767                 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));
2768                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2769                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2770                 {
2771                         if (rsurface.texture->pantstexture)
2772                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2773                         else
2774                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2775                 }
2776                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2777                 {
2778                         if (rsurface.texture->shirttexture)
2779                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2780                         else
2781                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2782                 }
2783                 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]);
2784                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2785                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2786                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2787                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2788                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2789                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2790                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2791                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2792                         );
2793                 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);
2794                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2795                 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]);
2796                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2797                 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);}
2798                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2799
2800                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2801                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2802                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2803                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2804                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2805                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2806                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2807                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2808                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2809                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2810                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2811                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2812                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2813                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2814                 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);
2815                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2816                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2817                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2818                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2819                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2820                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2821                 {
2822                         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);
2823                         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);
2824                         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);
2825                 }
2826                 else
2827                 {
2828                         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);
2829                 }
2830                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2831                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2832                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2833                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2834                 {
2835                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2836                         if (rsurface.rtlight)
2837                         {
2838                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2839                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2840                         }
2841                 }
2842                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2843                 CHECKGLERROR
2844                 break;
2845         case RENDERPATH_GL11:
2846         case RENDERPATH_GL13:
2847         case RENDERPATH_GLES1:
2848                 break;
2849         case RENDERPATH_SOFT:
2850                 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), texturenumsurfaces, texturesurfacelist);
2851                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2852                 R_SetupShader_SetPermutationSoft(mode, permutation);
2853                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2854                 if (mode == SHADERMODE_LIGHTSOURCE)
2855                 {
2856                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2857                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2858                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2859                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2860                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2861                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2862         
2863                         // additive passes are only darkened by fog, not tinted
2864                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2865                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2866                 }
2867                 else
2868                 {
2869                         if (mode == SHADERMODE_FLATCOLOR)
2870                         {
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2872                         }
2873                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2874                         {
2875                                 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]);
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2877                                 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);
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2880                                 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]);
2881                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2882                         }
2883                         else
2884                         {
2885                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2886                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2887                                 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);
2888                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2889                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2890                         }
2891                         // additive passes are only darkened by fog, not tinted
2892                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2893                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2894                         else
2895                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2896                         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);
2897                         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]);
2898                         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]);
2899                         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]);
2900                         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]);
2901                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2902                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2903                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2904                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2905                 }
2906                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2907                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2908                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2909                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2910                 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]);
2911
2912                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2913                 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));
2914                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2915                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2916                 {
2917                         if (rsurface.texture->pantstexture)
2918                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2919                         else
2920                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2921                 }
2922                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2923                 {
2924                         if (rsurface.texture->shirttexture)
2925                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2926                         else
2927                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2928                 }
2929                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2930                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2931                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2932                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2933                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2934                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2935                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2936                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2937                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2938                         );
2939                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2940                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2941                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2942                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2943
2944                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2945                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2946                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2947                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2948                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2949                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2950                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2951                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2952                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2953                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2954                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2955                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2956                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2957                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2958                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2959                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2960                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2961                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2962                 {
2963                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2964                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2965                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2966                 }
2967                 else
2968                 {
2969                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2970                 }
2971 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2972                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2973                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2974                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2975                 {
2976                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2977                         if (rsurface.rtlight)
2978                         {
2979                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2980                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2981                         }
2982                 }
2983                 break;
2984         }
2985 }
2986
2987 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2988 {
2989         // select a permutation of the lighting shader appropriate to this
2990         // combination of texture, entity, light source, and fogging, only use the
2991         // minimum features necessary to avoid wasting rendering time in the
2992         // fragment shader on features that are not being used
2993         unsigned int permutation = 0;
2994         unsigned int mode = 0;
2995         const float *lightcolorbase = rtlight->currentcolor;
2996         float ambientscale = rtlight->ambientscale;
2997         float diffusescale = rtlight->diffusescale;
2998         float specularscale = rtlight->specularscale;
2999         // this is the location of the light in view space
3000         vec3_t viewlightorigin;
3001         // this transforms from view space (camera) to light space (cubemap)
3002         matrix4x4_t viewtolight;
3003         matrix4x4_t lighttoview;
3004         float viewtolight16f[16];
3005         // light source
3006         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3007         if (rtlight->currentcubemap != r_texture_whitecube)
3008                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3009         if (diffusescale > 0)
3010                 permutation |= SHADERPERMUTATION_DIFFUSE;
3011         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3012                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3013         if (r_shadow_usingshadowmap2d)
3014         {
3015                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3016                 if (r_shadow_shadowmapvsdct)
3017                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3018
3019                 if (r_shadow_shadowmap2ddepthbuffer)
3020                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3021         }
3022         if (vid.allowalphatocoverage)
3023                 GL_AlphaToCoverage(false);
3024         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3025         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3026         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3027         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3028         switch(vid.renderpath)
3029         {
3030         case RENDERPATH_D3D9:
3031 #ifdef SUPPORTD3D
3032                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3033                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3034                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3035                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3036                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3037                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3038                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3039                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3040                 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);
3041                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3042                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3043
3044                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3045                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3046                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3047                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3048                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3049 #endif
3050                 break;
3051         case RENDERPATH_D3D10:
3052                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3053                 break;
3054         case RENDERPATH_D3D11:
3055                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3056                 break;
3057         case RENDERPATH_GL20:
3058         case RENDERPATH_GLES2:
3059                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3060                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3061                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3062                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3063                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3064                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3065                 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]);
3066                 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]);
3067                 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);
3068                 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]);
3069                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3070
3071                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3072                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3073                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3074                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3075                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3076                 break;
3077         case RENDERPATH_GL11:
3078         case RENDERPATH_GL13:
3079         case RENDERPATH_GLES1:
3080                 break;
3081         case RENDERPATH_SOFT:
3082                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3083                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3084                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3085                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3086                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3087                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3088                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3089                 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]);
3090                 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);
3091                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3092                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3093
3094                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3095                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3096                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3097                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3098                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3099                 break;
3100         }
3101 }
3102
3103 #define SKINFRAME_HASH 1024
3104
3105 typedef struct
3106 {
3107         int loadsequence; // incremented each level change
3108         memexpandablearray_t array;
3109         skinframe_t *hash[SKINFRAME_HASH];
3110 }
3111 r_skinframe_t;
3112 r_skinframe_t r_skinframe;
3113
3114 void R_SkinFrame_PrepareForPurge(void)
3115 {
3116         r_skinframe.loadsequence++;
3117         // wrap it without hitting zero
3118         if (r_skinframe.loadsequence >= 200)
3119                 r_skinframe.loadsequence = 1;
3120 }
3121
3122 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3123 {
3124         if (!skinframe)
3125                 return;
3126         // mark the skinframe as used for the purging code
3127         skinframe->loadsequence = r_skinframe.loadsequence;
3128 }
3129
3130 void R_SkinFrame_Purge(void)
3131 {
3132         int i;
3133         skinframe_t *s;
3134         for (i = 0;i < SKINFRAME_HASH;i++)
3135         {
3136                 for (s = r_skinframe.hash[i];s;s = s->next)
3137                 {
3138                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3139                         {
3140                                 if (s->merged == s->base)
3141                                         s->merged = NULL;
3142                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3143                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3144                                 R_PurgeTexture(s->merged);s->merged = NULL;
3145                                 R_PurgeTexture(s->base  );s->base   = NULL;
3146                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3147                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3148                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3149                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3150                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3151                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3152                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3153                                 s->loadsequence = 0;
3154                         }
3155                 }
3156         }
3157 }
3158
3159 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3160         skinframe_t *item;
3161         char basename[MAX_QPATH];
3162
3163         Image_StripImageExtension(name, basename, sizeof(basename));
3164
3165         if( last == NULL ) {
3166                 int hashindex;
3167                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3168                 item = r_skinframe.hash[hashindex];
3169         } else {
3170                 item = last->next;
3171         }
3172
3173         // linearly search through the hash bucket
3174         for( ; item ; item = item->next ) {
3175                 if( !strcmp( item->basename, basename ) ) {
3176                         return item;
3177                 }
3178         }
3179         return NULL;
3180 }
3181
3182 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3183 {
3184         skinframe_t *item;
3185         int hashindex;
3186         char basename[MAX_QPATH];
3187
3188         Image_StripImageExtension(name, basename, sizeof(basename));
3189
3190         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3191         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3192                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3193                         break;
3194
3195         if (!item) {
3196                 rtexture_t *dyntexture;
3197                 // check whether its a dynamic texture
3198                 dyntexture = CL_GetDynTexture( basename );
3199                 if (!add && !dyntexture)
3200                         return NULL;
3201                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3202                 memset(item, 0, sizeof(*item));
3203                 strlcpy(item->basename, basename, sizeof(item->basename));
3204                 item->base = dyntexture; // either NULL or dyntexture handle
3205                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3206                 item->comparewidth = comparewidth;
3207                 item->compareheight = compareheight;
3208                 item->comparecrc = comparecrc;
3209                 item->next = r_skinframe.hash[hashindex];
3210                 r_skinframe.hash[hashindex] = item;
3211         }
3212         else if (textureflags & TEXF_FORCE_RELOAD)
3213         {
3214                 rtexture_t *dyntexture;
3215                 // check whether its a dynamic texture
3216                 dyntexture = CL_GetDynTexture( basename );
3217                 if (!add && !dyntexture)
3218                         return NULL;
3219                 if (item->merged == item->base)
3220                         item->merged = NULL;
3221                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3222                 R_PurgeTexture(item->stain );item->stain  = NULL;
3223                 R_PurgeTexture(item->merged);item->merged = NULL;
3224                 R_PurgeTexture(item->base  );item->base   = NULL;
3225                 R_PurgeTexture(item->pants );item->pants  = NULL;
3226                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3227                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3228                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3229                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3230                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3231         R_PurgeTexture(item->reflect);item->reflect = NULL;
3232                 item->loadsequence = 0;
3233         }
3234         else if( item->base == NULL )
3235         {
3236                 rtexture_t *dyntexture;
3237                 // check whether its a dynamic texture
3238                 // 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]
3239                 dyntexture = CL_GetDynTexture( basename );
3240                 item->base = dyntexture; // either NULL or dyntexture handle
3241         }
3242
3243         R_SkinFrame_MarkUsed(item);
3244         return item;
3245 }
3246
3247 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3248         { \
3249                 unsigned long long avgcolor[5], wsum; \
3250                 int pix, comp, w; \
3251                 avgcolor[0] = 0; \
3252                 avgcolor[1] = 0; \
3253                 avgcolor[2] = 0; \
3254                 avgcolor[3] = 0; \
3255                 avgcolor[4] = 0; \
3256                 wsum = 0; \
3257                 for(pix = 0; pix < cnt; ++pix) \
3258                 { \
3259                         w = 0; \
3260                         for(comp = 0; comp < 3; ++comp) \
3261                                 w += getpixel; \
3262                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3263                         { \
3264                                 ++wsum; \
3265                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3266                                 w = getpixel; \
3267                                 for(comp = 0; comp < 3; ++comp) \
3268                                         avgcolor[comp] += getpixel * w; \
3269                                 avgcolor[3] += w; \
3270                         } \
3271                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3272                         avgcolor[4] += getpixel; \
3273                 } \
3274                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3275                         avgcolor[3] = 1; \
3276                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3277                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3278                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3279                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3280         }
3281
3282 extern cvar_t gl_picmip;
3283 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3284 {
3285         int j;
3286         unsigned char *pixels;
3287         unsigned char *bumppixels;
3288         unsigned char *basepixels = NULL;
3289         int basepixels_width = 0;
3290         int basepixels_height = 0;
3291         skinframe_t *skinframe;
3292         rtexture_t *ddsbase = NULL;
3293         qboolean ddshasalpha = false;
3294         float ddsavgcolor[4];
3295         char basename[MAX_QPATH];
3296         int miplevel = R_PicmipForFlags(textureflags);
3297         int savemiplevel = miplevel;
3298         int mymiplevel;
3299         char vabuf[1024];
3300
3301         if (cls.state == ca_dedicated)
3302                 return NULL;
3303
3304         // return an existing skinframe if already loaded
3305         // if loading of the first image fails, don't make a new skinframe as it
3306         // would cause all future lookups of this to be missing
3307         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3308         if (skinframe && skinframe->base)
3309                 return skinframe;
3310
3311         Image_StripImageExtension(name, basename, sizeof(basename));
3312
3313         // check for DDS texture file first
3314         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3315         {
3316                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3317                 if (basepixels == NULL)
3318                         return NULL;
3319         }
3320
3321         // FIXME handle miplevel
3322
3323         if (developer_loading.integer)
3324                 Con_Printf("loading skin \"%s\"\n", name);
3325
3326         // we've got some pixels to store, so really allocate this new texture now
3327         if (!skinframe)
3328                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3329         textureflags &= ~TEXF_FORCE_RELOAD;
3330         skinframe->stain = NULL;
3331         skinframe->merged = NULL;
3332         skinframe->base = NULL;
3333         skinframe->pants = NULL;
3334         skinframe->shirt = NULL;
3335         skinframe->nmap = NULL;
3336         skinframe->gloss = NULL;
3337         skinframe->glow = NULL;
3338         skinframe->fog = NULL;
3339         skinframe->reflect = NULL;
3340         skinframe->hasalpha = false;
3341
3342         if (ddsbase)
3343         {
3344                 skinframe->base = ddsbase;
3345                 skinframe->hasalpha = ddshasalpha;
3346                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3347                 if (r_loadfog && skinframe->hasalpha)
3348                         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);
3349                 //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]);
3350         }
3351         else
3352         {
3353                 basepixels_width = image_width;
3354                 basepixels_height = image_height;
3355                 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);
3356                 if (textureflags & TEXF_ALPHA)
3357                 {
3358                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3359                         {
3360                                 if (basepixels[j] < 255)
3361                                 {
3362                                         skinframe->hasalpha = true;
3363                                         break;
3364                                 }
3365                         }
3366                         if (r_loadfog && skinframe->hasalpha)
3367                         {
3368                                 // has transparent pixels
3369                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3370                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3371                                 {
3372                                         pixels[j+0] = 255;
3373                                         pixels[j+1] = 255;
3374                                         pixels[j+2] = 255;
3375                                         pixels[j+3] = basepixels[j+3];
3376                                 }
3377                                 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);
3378                                 Mem_Free(pixels);
3379                         }
3380                 }
3381                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3382 #ifndef USE_GLES2
3383                 //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]);
3384                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3385                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3386                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3387                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3388 #endif
3389         }
3390
3391         if (r_loaddds)
3392         {
3393                 mymiplevel = savemiplevel;
3394                 if (r_loadnormalmap)
3395                         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);
3396                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3397                 if (r_loadgloss)
3398                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3399                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3400                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3401                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3402         }
3403
3404         // _norm is the name used by tenebrae and has been adopted as standard
3405         if (r_loadnormalmap && skinframe->nmap == NULL)
3406         {
3407                 mymiplevel = savemiplevel;
3408                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3409                 {
3410                         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);
3411                         Mem_Free(pixels);
3412                         pixels = NULL;
3413                 }
3414                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3415                 {
3416                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3417                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3418                         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);
3419                         Mem_Free(pixels);
3420                         Mem_Free(bumppixels);
3421                 }
3422                 else if (r_shadow_bumpscale_basetexture.value > 0)
3423                 {
3424                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3425                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3426                         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);
3427                         Mem_Free(pixels);
3428                 }
3429 #ifndef USE_GLES2
3430                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3431                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3432 #endif
3433         }
3434
3435         // _luma is supported only for tenebrae compatibility
3436         // _glow is the preferred name
3437         mymiplevel = savemiplevel;
3438         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))))
3439         {
3440                 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);
3441 #ifndef USE_GLES2
3442                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3443                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3444 #endif
3445                 Mem_Free(pixels);pixels = NULL;
3446         }
3447
3448         mymiplevel = savemiplevel;
3449         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3450         {
3451                 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);
3452 #ifndef USE_GLES2
3453                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3454                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3455 #endif
3456                 Mem_Free(pixels);
3457                 pixels = NULL;
3458         }
3459
3460         mymiplevel = savemiplevel;
3461         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3462         {
3463                 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);
3464 #ifndef USE_GLES2
3465                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3466                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3467 #endif
3468                 Mem_Free(pixels);
3469                 pixels = NULL;
3470         }
3471
3472         mymiplevel = savemiplevel;
3473         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3474         {
3475                 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);
3476 #ifndef USE_GLES2
3477                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3478                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3479 #endif
3480                 Mem_Free(pixels);
3481                 pixels = NULL;
3482         }
3483
3484         mymiplevel = savemiplevel;
3485         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3486         {
3487                 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);
3488 #ifndef USE_GLES2
3489                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3490                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3491 #endif
3492                 Mem_Free(pixels);
3493                 pixels = NULL;
3494         }
3495
3496         if (basepixels)
3497                 Mem_Free(basepixels);
3498
3499         return skinframe;
3500 }
3501
3502 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3503 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3504 {
3505         int i;
3506         unsigned char *temp1, *temp2;
3507         skinframe_t *skinframe;
3508         char vabuf[1024];
3509
3510         if (cls.state == ca_dedicated)
3511                 return NULL;
3512
3513         // if already loaded just return it, otherwise make a new skinframe
3514         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3515         if (skinframe->base)
3516                 return skinframe;
3517         textureflags &= ~TEXF_FORCE_RELOAD;
3518
3519         skinframe->stain = NULL;
3520         skinframe->merged = NULL;
3521         skinframe->base = NULL;
3522         skinframe->pants = NULL;
3523         skinframe->shirt = NULL;
3524         skinframe->nmap = NULL;
3525         skinframe->gloss = NULL;
3526         skinframe->glow = NULL;
3527         skinframe->fog = NULL;
3528         skinframe->reflect = NULL;
3529         skinframe->hasalpha = false;
3530
3531         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3532         if (!skindata)
3533                 return NULL;
3534
3535         if (developer_loading.integer)
3536                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3537
3538         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3539         {
3540                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3541                 temp2 = temp1 + width * height * 4;
3542                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3543                 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);
3544                 Mem_Free(temp1);
3545         }
3546         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3547         if (textureflags & TEXF_ALPHA)
3548         {
3549                 for (i = 3;i < width * height * 4;i += 4)
3550                 {
3551                         if (skindata[i] < 255)
3552                         {
3553                                 skinframe->hasalpha = true;
3554                                 break;
3555                         }
3556                 }
3557                 if (r_loadfog && skinframe->hasalpha)
3558                 {
3559                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3560                         memcpy(fogpixels, skindata, width * height * 4);
3561                         for (i = 0;i < width * height * 4;i += 4)
3562                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3563                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3564                         Mem_Free(fogpixels);
3565                 }
3566         }
3567
3568         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3569         //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]);
3570
3571         return skinframe;
3572 }
3573
3574 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3575 {
3576         int i;
3577         int featuresmask;
3578         skinframe_t *skinframe;
3579
3580         if (cls.state == ca_dedicated)
3581                 return NULL;
3582
3583         // if already loaded just return it, otherwise make a new skinframe
3584         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3585         if (skinframe->base)
3586                 return skinframe;
3587         //textureflags &= ~TEXF_FORCE_RELOAD;
3588
3589         skinframe->stain = NULL;
3590         skinframe->merged = NULL;
3591         skinframe->base = NULL;
3592         skinframe->pants = NULL;
3593         skinframe->shirt = NULL;
3594         skinframe->nmap = NULL;
3595         skinframe->gloss = NULL;
3596         skinframe->glow = NULL;
3597         skinframe->fog = NULL;
3598         skinframe->reflect = NULL;
3599         skinframe->hasalpha = false;
3600
3601         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3602         if (!skindata)
3603                 return NULL;
3604
3605         if (developer_loading.integer)
3606                 Con_Printf("loading quake skin \"%s\"\n", name);
3607
3608         // 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)
3609         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3610         memcpy(skinframe->qpixels, skindata, width*height);
3611         skinframe->qwidth = width;
3612         skinframe->qheight = height;
3613
3614         featuresmask = 0;
3615         for (i = 0;i < width * height;i++)
3616                 featuresmask |= palette_featureflags[skindata[i]];
3617
3618         skinframe->hasalpha = false;
3619         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3620         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3621         skinframe->qgeneratemerged = true;
3622         skinframe->qgeneratebase = skinframe->qhascolormapping;
3623         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3624
3625         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3626         //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]);
3627
3628         return skinframe;
3629 }
3630
3631 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3632 {
3633         int width;
3634         int height;
3635         unsigned char *skindata;
3636         char vabuf[1024];
3637
3638         if (!skinframe->qpixels)
3639                 return;
3640
3641         if (!skinframe->qhascolormapping)
3642                 colormapped = false;
3643
3644         if (colormapped)
3645         {
3646                 if (!skinframe->qgeneratebase)
3647                         return;
3648         }
3649         else
3650         {
3651                 if (!skinframe->qgeneratemerged)
3652                         return;
3653         }
3654
3655         width = skinframe->qwidth;
3656         height = skinframe->qheight;
3657         skindata = skinframe->qpixels;
3658
3659         if (skinframe->qgeneratenmap)
3660         {
3661                 unsigned char *temp1, *temp2;
3662                 skinframe->qgeneratenmap = false;
3663                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3664                 temp2 = temp1 + width * height * 4;
3665                 // use either a custom palette or the quake palette
3666                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3667                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3668                 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);
3669                 Mem_Free(temp1);
3670         }
3671
3672         if (skinframe->qgenerateglow)
3673         {
3674                 skinframe->qgenerateglow = false;
3675                 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
3676         }
3677
3678         if (colormapped)
3679         {
3680                 skinframe->qgeneratebase = false;
3681                 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);
3682                 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);
3683                 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);
3684         }
3685         else
3686         {
3687                 skinframe->qgeneratemerged = false;
3688                 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);
3689         }
3690
3691         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3692         {
3693                 Mem_Free(skinframe->qpixels);
3694                 skinframe->qpixels = NULL;
3695         }
3696 }
3697
3698 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)
3699 {
3700         int i;
3701         skinframe_t *skinframe;
3702         char vabuf[1024];
3703
3704         if (cls.state == ca_dedicated)
3705                 return NULL;
3706
3707         // if already loaded just return it, otherwise make a new skinframe
3708         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3709         if (skinframe->base)
3710                 return skinframe;
3711         textureflags &= ~TEXF_FORCE_RELOAD;
3712
3713         skinframe->stain = NULL;
3714         skinframe->merged = NULL;
3715         skinframe->base = NULL;
3716         skinframe->pants = NULL;
3717         skinframe->shirt = NULL;
3718         skinframe->nmap = NULL;
3719         skinframe->gloss = NULL;
3720         skinframe->glow = NULL;
3721         skinframe->fog = NULL;
3722         skinframe->reflect = NULL;
3723         skinframe->hasalpha = false;
3724
3725         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3726         if (!skindata)
3727                 return NULL;
3728
3729         if (developer_loading.integer)
3730                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3731
3732         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3733         if (textureflags & TEXF_ALPHA)
3734         {
3735                 for (i = 0;i < width * height;i++)
3736                 {
3737                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3738                         {
3739                                 skinframe->hasalpha = true;
3740                                 break;
3741                         }
3742                 }
3743                 if (r_loadfog && skinframe->hasalpha)
3744                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3745         }
3746
3747         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3748         //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]);
3749
3750         return skinframe;
3751 }
3752
3753 skinframe_t *R_SkinFrame_LoadMissing(void)
3754 {
3755         skinframe_t *skinframe;
3756
3757         if (cls.state == ca_dedicated)
3758                 return NULL;
3759
3760         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3761         skinframe->stain = NULL;
3762         skinframe->merged = NULL;
3763         skinframe->base = NULL;
3764         skinframe->pants = NULL;
3765         skinframe->shirt = NULL;
3766         skinframe->nmap = NULL;
3767         skinframe->gloss = NULL;
3768         skinframe->glow = NULL;
3769         skinframe->fog = NULL;
3770         skinframe->reflect = NULL;
3771         skinframe->hasalpha = false;
3772
3773         skinframe->avgcolor[0] = rand() / RAND_MAX;
3774         skinframe->avgcolor[1] = rand() / RAND_MAX;
3775         skinframe->avgcolor[2] = rand() / RAND_MAX;
3776         skinframe->avgcolor[3] = 1;
3777
3778         return skinframe;
3779 }
3780
3781 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3782 typedef struct suffixinfo_s
3783 {
3784         const char *suffix;
3785         qboolean flipx, flipy, flipdiagonal;
3786 }
3787 suffixinfo_t;
3788 static suffixinfo_t suffix[3][6] =
3789 {
3790         {
3791                 {"px",   false, false, false},
3792                 {"nx",   false, false, false},
3793                 {"py",   false, false, false},
3794                 {"ny",   false, false, false},
3795                 {"pz",   false, false, false},
3796                 {"nz",   false, false, false}
3797         },
3798         {
3799                 {"posx", false, false, false},
3800                 {"negx", false, false, false},
3801                 {"posy", false, false, false},
3802                 {"negy", false, false, false},
3803                 {"posz", false, false, false},
3804                 {"negz", false, false, false}
3805         },
3806         {
3807                 {"rt",    true, false,  true},
3808                 {"lf",   false,  true,  true},
3809                 {"ft",    true,  true, false},
3810                 {"bk",   false, false, false},
3811                 {"up",    true, false,  true},
3812                 {"dn",    true, false,  true}
3813         }
3814 };
3815
3816 static int componentorder[4] = {0, 1, 2, 3};
3817
3818 static rtexture_t *R_LoadCubemap(const char *basename)
3819 {
3820         int i, j, cubemapsize;
3821         unsigned char *cubemappixels, *image_buffer;
3822         rtexture_t *cubemaptexture;
3823         char name[256];
3824         // must start 0 so the first loadimagepixels has no requested width/height
3825         cubemapsize = 0;
3826         cubemappixels = NULL;
3827         cubemaptexture = NULL;
3828         // keep trying different suffix groups (posx, px, rt) until one loads
3829         for (j = 0;j < 3 && !cubemappixels;j++)
3830         {
3831                 // load the 6 images in the suffix group
3832                 for (i = 0;i < 6;i++)
3833                 {
3834                         // generate an image name based on the base and and suffix
3835                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3836                         // load it
3837                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3838                         {
3839                                 // an image loaded, make sure width and height are equal
3840                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3841                                 {
3842                                         // if this is the first image to load successfully, allocate the cubemap memory
3843                                         if (!cubemappixels && image_width >= 1)
3844                                         {
3845                                                 cubemapsize = image_width;
3846                                                 // note this clears to black, so unavailable sides are black
3847                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3848                                         }
3849                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3850                                         if (cubemappixels)
3851                                                 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);
3852                                 }
3853                                 else
3854                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3855                                 // free the image
3856                                 Mem_Free(image_buffer);
3857                         }
3858                 }
3859         }
3860         // if a cubemap loaded, upload it
3861         if (cubemappixels)
3862         {
3863                 if (developer_loading.integer)
3864                         Con_Printf("loading cubemap \"%s\"\n", basename);
3865
3866                 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);
3867                 Mem_Free(cubemappixels);
3868         }
3869         else
3870         {
3871                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3872                 if (developer_loading.integer)
3873                 {
3874                         Con_Printf("(tried tried images ");
3875                         for (j = 0;j < 3;j++)
3876                                 for (i = 0;i < 6;i++)
3877                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3878                         Con_Print(" and was unable to find any of them).\n");
3879                 }
3880         }
3881         return cubemaptexture;
3882 }
3883
3884 rtexture_t *R_GetCubemap(const char *basename)
3885 {
3886         int i;
3887         for (i = 0;i < r_texture_numcubemaps;i++)
3888                 if (r_texture_cubemaps[i] != NULL)
3889                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3890                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3891         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3892                 return r_texture_whitecube;
3893         r_texture_numcubemaps++;
3894         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3895         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3896         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3897         return r_texture_cubemaps[i]->texture;
3898 }
3899
3900 static void R_Main_FreeViewCache(void)
3901 {
3902         if (r_refdef.viewcache.entityvisible)
3903                 Mem_Free(r_refdef.viewcache.entityvisible);
3904         if (r_refdef.viewcache.world_pvsbits)
3905                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3906         if (r_refdef.viewcache.world_leafvisible)
3907                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3908         if (r_refdef.viewcache.world_surfacevisible)
3909                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3910         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3911 }
3912
3913 static void R_Main_ResizeViewCache(void)
3914 {
3915         int numentities = r_refdef.scene.numentities;
3916         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3917         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3918         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3919         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3920         if (r_refdef.viewcache.maxentities < numentities)
3921         {
3922                 r_refdef.viewcache.maxentities = numentities;
3923                 if (r_refdef.viewcache.entityvisible)
3924                         Mem_Free(r_refdef.viewcache.entityvisible);
3925                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3926         }
3927         if (r_refdef.viewcache.world_numclusters != numclusters)
3928         {
3929                 r_refdef.viewcache.world_numclusters = numclusters;
3930                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3931                 if (r_refdef.viewcache.world_pvsbits)
3932                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3933                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3934         }
3935         if (r_refdef.viewcache.world_numleafs != numleafs)
3936         {
3937                 r_refdef.viewcache.world_numleafs = numleafs;
3938                 if (r_refdef.viewcache.world_leafvisible)
3939                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3940                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3941         }
3942         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3943         {
3944                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3945                 if (r_refdef.viewcache.world_surfacevisible)
3946                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3947                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3948         }
3949 }
3950
3951 extern rtexture_t *loadingscreentexture;
3952 static void gl_main_start(void)
3953 {
3954         loadingscreentexture = NULL;
3955         r_texture_blanknormalmap = NULL;
3956         r_texture_white = NULL;
3957         r_texture_grey128 = NULL;
3958         r_texture_black = NULL;
3959         r_texture_whitecube = NULL;
3960         r_texture_normalizationcube = NULL;
3961         r_texture_fogattenuation = NULL;
3962         r_texture_fogheighttexture = NULL;
3963         r_texture_gammaramps = NULL;
3964         r_texture_numcubemaps = 0;
3965
3966         r_loaddds = r_texture_dds_load.integer != 0;
3967         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3968
3969         switch(vid.renderpath)
3970         {
3971         case RENDERPATH_GL20:
3972         case RENDERPATH_D3D9:
3973         case RENDERPATH_D3D10:
3974         case RENDERPATH_D3D11:
3975         case RENDERPATH_SOFT:
3976         case RENDERPATH_GLES2:
3977                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3978                 Cvar_SetValueQuick(&gl_combine, 1);
3979                 Cvar_SetValueQuick(&r_glsl, 1);
3980                 r_loadnormalmap = true;
3981                 r_loadgloss = true;
3982                 r_loadfog = false;
3983                 break;
3984         case RENDERPATH_GL13:
3985         case RENDERPATH_GLES1:
3986                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3987                 Cvar_SetValueQuick(&gl_combine, 1);
3988                 Cvar_SetValueQuick(&r_glsl, 0);
3989                 r_loadnormalmap = false;
3990                 r_loadgloss = false;
3991                 r_loadfog = true;
3992                 break;
3993         case RENDERPATH_GL11:
3994                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3995                 Cvar_SetValueQuick(&gl_combine, 0);
3996                 Cvar_SetValueQuick(&r_glsl, 0);
3997                 r_loadnormalmap = false;
3998                 r_loadgloss = false;
3999                 r_loadfog = true;
4000                 break;
4001         }
4002
4003         R_AnimCache_Free();
4004         R_FrameData_Reset();
4005
4006         r_numqueries = 0;
4007         r_maxqueries = 0;
4008         memset(r_queries, 0, sizeof(r_queries));
4009
4010         r_qwskincache = NULL;
4011         r_qwskincache_size = 0;
4012
4013         // due to caching of texture_t references, the collision cache must be reset
4014         Collision_Cache_Reset(true);
4015
4016         // set up r_skinframe loading system for textures
4017         memset(&r_skinframe, 0, sizeof(r_skinframe));
4018         r_skinframe.loadsequence = 1;
4019         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4020
4021         r_main_texturepool = R_AllocTexturePool();
4022         R_BuildBlankTextures();
4023         R_BuildNoTexture();
4024         if (vid.support.arb_texture_cube_map)
4025         {
4026                 R_BuildWhiteCube();
4027                 R_BuildNormalizationCube();
4028         }
4029         r_texture_fogattenuation = NULL;
4030         r_texture_fogheighttexture = NULL;
4031         r_texture_gammaramps = NULL;
4032         //r_texture_fogintensity = NULL;
4033         memset(&r_fb, 0, sizeof(r_fb));
4034         r_glsl_permutation = NULL;
4035         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4036         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4037         glslshaderstring = NULL;
4038 #ifdef SUPPORTD3D
4039         r_hlsl_permutation = NULL;
4040         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4041         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4042 #endif
4043         hlslshaderstring = NULL;
4044         memset(&r_svbsp, 0, sizeof (r_svbsp));
4045
4046         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4047         r_texture_numcubemaps = 0;
4048
4049         r_refdef.fogmasktable_density = 0;
4050 }
4051
4052 static void gl_main_shutdown(void)
4053 {
4054         R_AnimCache_Free();
4055         R_FrameData_Reset();
4056
4057         R_Main_FreeViewCache();
4058
4059         switch(vid.renderpath)
4060         {
4061         case RENDERPATH_GL11:
4062         case RENDERPATH_GL13:
4063         case RENDERPATH_GL20:
4064         case RENDERPATH_GLES1:
4065         case RENDERPATH_GLES2:
4066 #ifdef GL_SAMPLES_PASSED_ARB
4067                 if (r_maxqueries)
4068                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4069 #endif
4070                 break;
4071         case RENDERPATH_D3D9:
4072                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4073                 break;
4074         case RENDERPATH_D3D10:
4075                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4076                 break;
4077         case RENDERPATH_D3D11:
4078                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4079                 break;
4080         case RENDERPATH_SOFT:
4081                 break;
4082         }
4083
4084         r_numqueries = 0;
4085         r_maxqueries = 0;
4086         memset(r_queries, 0, sizeof(r_queries));
4087
4088         r_qwskincache = NULL;
4089         r_qwskincache_size = 0;
4090
4091         // clear out the r_skinframe state
4092         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4093         memset(&r_skinframe, 0, sizeof(r_skinframe));
4094
4095         if (r_svbsp.nodes)
4096                 Mem_Free(r_svbsp.nodes);
4097         memset(&r_svbsp, 0, sizeof (r_svbsp));
4098         R_FreeTexturePool(&r_main_texturepool);
4099         loadingscreentexture = NULL;
4100         r_texture_blanknormalmap = NULL;
4101         r_texture_white = NULL;
4102         r_texture_grey128 = NULL;
4103         r_texture_black = NULL;
4104         r_texture_whitecube = NULL;
4105         r_texture_normalizationcube = NULL;
4106         r_texture_fogattenuation = NULL;
4107         r_texture_fogheighttexture = NULL;
4108         r_texture_gammaramps = NULL;
4109         r_texture_numcubemaps = 0;
4110         //r_texture_fogintensity = NULL;
4111         memset(&r_fb, 0, sizeof(r_fb));
4112         R_GLSL_Restart_f();
4113
4114         r_glsl_permutation = NULL;
4115         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4116         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4117         glslshaderstring = NULL;
4118 #ifdef SUPPORTD3D
4119         r_hlsl_permutation = NULL;
4120         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4121         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4122 #endif
4123         hlslshaderstring = NULL;
4124 }
4125
4126 static void gl_main_newmap(void)
4127 {
4128         // FIXME: move this code to client
4129         char *entities, entname[MAX_QPATH];
4130         if (r_qwskincache)
4131                 Mem_Free(r_qwskincache);
4132         r_qwskincache = NULL;
4133         r_qwskincache_size = 0;
4134         if (cl.worldmodel)
4135         {
4136                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4137                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4138                 {
4139                         CL_ParseEntityLump(entities);
4140                         Mem_Free(entities);
4141                         return;
4142                 }
4143                 if (cl.worldmodel->brush.entities)
4144                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4145         }
4146         R_Main_FreeViewCache();
4147
4148         R_FrameData_Reset();
4149 }
4150
4151 void GL_Main_Init(void)
4152 {
4153         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4154
4155         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4156         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4157         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4158         if (gamemode == GAME_NEHAHRA)
4159         {
4160                 Cvar_RegisterVariable (&gl_fogenable);
4161                 Cvar_RegisterVariable (&gl_fogdensity);
4162                 Cvar_RegisterVariable (&gl_fogred);
4163                 Cvar_RegisterVariable (&gl_foggreen);
4164                 Cvar_RegisterVariable (&gl_fogblue);
4165                 Cvar_RegisterVariable (&gl_fogstart);
4166                 Cvar_RegisterVariable (&gl_fogend);
4167                 Cvar_RegisterVariable (&gl_skyclip);
4168         }
4169         Cvar_RegisterVariable(&r_motionblur);
4170         Cvar_RegisterVariable(&r_damageblur);
4171         Cvar_RegisterVariable(&r_motionblur_averaging);
4172         Cvar_RegisterVariable(&r_motionblur_randomize);
4173         Cvar_RegisterVariable(&r_motionblur_minblur);
4174         Cvar_RegisterVariable(&r_motionblur_maxblur);
4175         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4176         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4177         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4178         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4179         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4180         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4181         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4182         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4183         Cvar_RegisterVariable(&r_equalize_entities_by);
4184         Cvar_RegisterVariable(&r_equalize_entities_to);
4185         Cvar_RegisterVariable(&r_depthfirst);
4186         Cvar_RegisterVariable(&r_useinfinitefarclip);
4187         Cvar_RegisterVariable(&r_farclip_base);
4188         Cvar_RegisterVariable(&r_farclip_world);
4189         Cvar_RegisterVariable(&r_nearclip);
4190         Cvar_RegisterVariable(&r_deformvertexes);
4191         Cvar_RegisterVariable(&r_transparent);
4192         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4193         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4194         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4195         Cvar_RegisterVariable(&r_showoverdraw);
4196         Cvar_RegisterVariable(&r_showbboxes);
4197         Cvar_RegisterVariable(&r_showsurfaces);
4198         Cvar_RegisterVariable(&r_showtris);
4199         Cvar_RegisterVariable(&r_shownormals);
4200         Cvar_RegisterVariable(&r_showlighting);
4201         Cvar_RegisterVariable(&r_showshadowvolumes);
4202         Cvar_RegisterVariable(&r_showcollisionbrushes);
4203         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4204         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4205         Cvar_RegisterVariable(&r_showdisabledepthtest);
4206         Cvar_RegisterVariable(&r_drawportals);
4207         Cvar_RegisterVariable(&r_drawentities);
4208         Cvar_RegisterVariable(&r_draw2d);
4209         Cvar_RegisterVariable(&r_drawworld);
4210         Cvar_RegisterVariable(&r_cullentities_trace);
4211         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4212         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4213         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4214         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4215         Cvar_RegisterVariable(&r_sortentities);
4216         Cvar_RegisterVariable(&r_drawviewmodel);
4217         Cvar_RegisterVariable(&r_drawexteriormodel);
4218         Cvar_RegisterVariable(&r_speeds);
4219         Cvar_RegisterVariable(&r_fullbrights);
4220         Cvar_RegisterVariable(&r_wateralpha);
4221         Cvar_RegisterVariable(&r_dynamic);
4222         Cvar_RegisterVariable(&r_fakelight);
4223         Cvar_RegisterVariable(&r_fakelight_intensity);
4224         Cvar_RegisterVariable(&r_fullbright);
4225         Cvar_RegisterVariable(&r_shadows);
4226         Cvar_RegisterVariable(&r_shadows_darken);
4227         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4228         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4229         Cvar_RegisterVariable(&r_shadows_throwdistance);
4230         Cvar_RegisterVariable(&r_shadows_throwdirection);
4231         Cvar_RegisterVariable(&r_shadows_focus);
4232         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4233         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4234         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4235         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4236         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4237         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4238         Cvar_RegisterVariable(&r_fog_exp2);
4239         Cvar_RegisterVariable(&r_fog_clear);
4240         Cvar_RegisterVariable(&r_drawfog);
4241         Cvar_RegisterVariable(&r_transparentdepthmasking);
4242         Cvar_RegisterVariable(&r_transparent_sortmindist);
4243         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4244         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4245         Cvar_RegisterVariable(&r_texture_dds_load);
4246         Cvar_RegisterVariable(&r_texture_dds_save);
4247         Cvar_RegisterVariable(&r_textureunits);
4248         Cvar_RegisterVariable(&gl_combine);
4249         Cvar_RegisterVariable(&r_usedepthtextures);
4250         Cvar_RegisterVariable(&r_viewfbo);
4251         Cvar_RegisterVariable(&r_viewscale);
4252         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4253         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4254         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4255         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4256         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4257         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4258         Cvar_RegisterVariable(&r_glsl);
4259         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4260         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4261         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4262         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4263         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4264         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4265         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4266         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4267         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4268         Cvar_RegisterVariable(&r_glsl_postprocess);
4269         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4270         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4271         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4272         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4273         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4274         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4275         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4276         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4277         Cvar_RegisterVariable(&r_celshading);
4278         Cvar_RegisterVariable(&r_celoutlines);
4279
4280         Cvar_RegisterVariable(&r_water);
4281         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4282         Cvar_RegisterVariable(&r_water_clippingplanebias);
4283         Cvar_RegisterVariable(&r_water_refractdistort);
4284         Cvar_RegisterVariable(&r_water_reflectdistort);
4285         Cvar_RegisterVariable(&r_water_scissormode);
4286         Cvar_RegisterVariable(&r_water_lowquality);
4287         Cvar_RegisterVariable(&r_water_hideplayer);
4288         Cvar_RegisterVariable(&r_water_fbo);
4289
4290         Cvar_RegisterVariable(&r_lerpsprites);
4291         Cvar_RegisterVariable(&r_lerpmodels);
4292         Cvar_RegisterVariable(&r_lerplightstyles);
4293         Cvar_RegisterVariable(&r_waterscroll);
4294         Cvar_RegisterVariable(&r_bloom);
4295         Cvar_RegisterVariable(&r_bloom_colorscale);
4296         Cvar_RegisterVariable(&r_bloom_brighten);
4297         Cvar_RegisterVariable(&r_bloom_blur);
4298         Cvar_RegisterVariable(&r_bloom_resolution);
4299         Cvar_RegisterVariable(&r_bloom_colorexponent);
4300         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4301         Cvar_RegisterVariable(&r_bloom_scenebrightness);
4302         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4303         Cvar_RegisterVariable(&r_hdr_glowintensity);
4304         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4305         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4306         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4307         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4308         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4309         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4310         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4311         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4312         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4313         Cvar_RegisterVariable(&developer_texturelogging);
4314         Cvar_RegisterVariable(&gl_lightmaps);
4315         Cvar_RegisterVariable(&r_test);
4316         Cvar_RegisterVariable(&r_glsl_saturation);
4317         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4318         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4319         Cvar_RegisterVariable(&r_framedatasize);
4320         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4321                 Cvar_SetValue("r_fullbrights", 0);
4322         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4323 }
4324
4325 void Render_Init(void)
4326 {
4327         gl_backend_init();
4328         R_Textures_Init();
4329         GL_Main_Init();
4330         Font_Init();
4331         GL_Draw_Init();
4332         R_Shadow_Init();
4333         R_Sky_Init();
4334         GL_Surf_Init();
4335         Sbar_Init();
4336         R_Particles_Init();
4337         R_Explosion_Init();
4338         R_LightningBeams_Init();
4339         Mod_RenderInit();
4340 }
4341
4342 /*
4343 ===============
4344 GL_Init
4345 ===============
4346 */
4347 #ifndef USE_GLES2
4348 extern char *ENGINE_EXTENSIONS;
4349 void GL_Init (void)
4350 {
4351         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4352         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4353         gl_version = (const char *)qglGetString(GL_VERSION);
4354         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4355
4356         if (!gl_extensions)
4357                 gl_extensions = "";
4358         if (!gl_platformextensions)
4359                 gl_platformextensions = "";
4360
4361         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4362         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4363         Con_Printf("GL_VERSION: %s\n", gl_version);
4364         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4365         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4366
4367         VID_CheckExtensions();
4368
4369         // LordHavoc: report supported extensions
4370         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4371
4372         // clear to black (loading plaque will be seen over this)
4373         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4374 }
4375 #endif
4376
4377 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4378 {
4379         int i;
4380         mplane_t *p;
4381         if (r_trippy.integer)
4382                 return false;
4383         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4384         {
4385                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4386                 if (i == 4)
4387                         continue;
4388                 p = r_refdef.view.frustum + i;
4389                 switch(p->signbits)
4390                 {
4391                 default:
4392                 case 0:
4393                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4394                                 return true;
4395                         break;
4396                 case 1:
4397                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4398                                 return true;
4399                         break;
4400                 case 2:
4401                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4402                                 return true;
4403                         break;
4404                 case 3:
4405                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4406                                 return true;
4407                         break;
4408                 case 4:
4409                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4410                                 return true;
4411                         break;
4412                 case 5:
4413                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4414                                 return true;
4415                         break;
4416                 case 6:
4417                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4418                                 return true;
4419                         break;
4420                 case 7:
4421                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4422                                 return true;
4423                         break;
4424                 }
4425         }
4426         return false;
4427 }
4428
4429 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4430 {
4431         int i;
4432         const mplane_t *p;
4433         if (r_trippy.integer)
4434                 return false;
4435         for (i = 0;i < numplanes;i++)
4436         {
4437                 p = planes + i;
4438                 switch(p->signbits)
4439                 {
4440                 default:
4441                 case 0:
4442                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4443                                 return true;
4444                         break;
4445                 case 1:
4446                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4447                                 return true;
4448                         break;
4449                 case 2:
4450                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4451                                 return true;
4452                         break;
4453                 case 3:
4454                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4455                                 return true;
4456                         break;
4457                 case 4:
4458                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4459                                 return true;
4460                         break;
4461                 case 5:
4462                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4463                                 return true;
4464                         break;
4465                 case 6:
4466                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4467                                 return true;
4468                         break;
4469                 case 7:
4470                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4471                                 return true;
4472                         break;
4473                 }
4474         }
4475         return false;
4476 }
4477
4478 //==================================================================================
4479
4480 // LordHavoc: this stores temporary data used within the same frame
4481
4482 typedef struct r_framedata_mem_s
4483 {
4484         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4485         size_t size; // how much usable space
4486         size_t current; // how much space in use
4487         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4488         size_t wantedsize; // how much space was allocated
4489         unsigned char *data; // start of real data (16byte aligned)
4490 }
4491 r_framedata_mem_t;
4492
4493 static r_framedata_mem_t *r_framedata_mem;
4494
4495 void R_FrameData_Reset(void)
4496 {
4497         while (r_framedata_mem)
4498         {
4499                 r_framedata_mem_t *next = r_framedata_mem->purge;
4500                 Mem_Free(r_framedata_mem);
4501                 r_framedata_mem = next;
4502         }
4503 }
4504
4505 static void R_FrameData_Resize(void)
4506 {
4507         size_t wantedsize;
4508         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4509         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4510         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4511         {
4512                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4513                 newmem->wantedsize = wantedsize;
4514                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4515                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4516                 newmem->current = 0;
4517                 newmem->mark = 0;
4518                 newmem->purge = r_framedata_mem;
4519                 r_framedata_mem = newmem;
4520         }
4521 }
4522
4523 void R_FrameData_NewFrame(void)
4524 {
4525         R_FrameData_Resize();
4526         if (!r_framedata_mem)
4527                 return;
4528         // if we ran out of space on the last frame, free the old memory now
4529         while (r_framedata_mem->purge)
4530         {
4531                 // repeatedly remove the second item in the list, leaving only head
4532                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4533                 Mem_Free(r_framedata_mem->purge);
4534                 r_framedata_mem->purge = next;
4535         }
4536         // reset the current mem pointer
4537         r_framedata_mem->current = 0;
4538         r_framedata_mem->mark = 0;
4539 }
4540
4541 void *R_FrameData_Alloc(size_t size)
4542 {
4543         void *data;
4544
4545         // align to 16 byte boundary - the data pointer is already aligned, so we
4546         // only need to ensure the size of every allocation is also aligned
4547         size = (size + 15) & ~15;
4548
4549         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4550         {
4551                 // emergency - we ran out of space, allocate more memory
4552                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4553                 R_FrameData_Resize();
4554         }
4555
4556         data = r_framedata_mem->data + r_framedata_mem->current;
4557         r_framedata_mem->current += size;
4558
4559         // count the usage for stats
4560         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4561         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4562
4563         return (void *)data;
4564 }
4565
4566 void *R_FrameData_Store(size_t size, void *data)
4567 {
4568         void *d = R_FrameData_Alloc(size);
4569         if (d && data)
4570                 memcpy(d, data, size);
4571         return d;
4572 }
4573
4574 void R_FrameData_SetMark(void)
4575 {
4576         if (!r_framedata_mem)
4577                 return;
4578         r_framedata_mem->mark = r_framedata_mem->current;
4579 }
4580
4581 void R_FrameData_ReturnToMark(void)
4582 {
4583         if (!r_framedata_mem)
4584                 return;
4585         r_framedata_mem->current = r_framedata_mem->mark;
4586 }
4587
4588 //==================================================================================
4589
4590 // LordHavoc: animcache originally written by Echon, rewritten since then
4591
4592 /**
4593  * Animation cache prevents re-generating mesh data for an animated model
4594  * multiple times in one frame for lighting, shadowing, reflections, etc.
4595  */
4596
4597 void R_AnimCache_Free(void)
4598 {
4599 }
4600
4601 void R_AnimCache_ClearCache(void)
4602 {
4603         int i;
4604         entity_render_t *ent;
4605
4606         for (i = 0;i < r_refdef.scene.numentities;i++)
4607         {
4608                 ent = r_refdef.scene.entities[i];
4609                 ent->animcache_vertex3f = NULL;
4610                 ent->animcache_normal3f = NULL;
4611                 ent->animcache_svector3f = NULL;
4612                 ent->animcache_tvector3f = NULL;
4613                 ent->animcache_vertexmesh = NULL;
4614                 ent->animcache_vertex3fbuffer = NULL;
4615                 ent->animcache_vertexmeshbuffer = NULL;
4616         }
4617 }
4618
4619 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4620 {
4621         int i;
4622
4623         // check if we need the meshbuffers
4624         if (!vid.useinterleavedarrays)
4625                 return;
4626
4627         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4628                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4629         // TODO: upload vertex3f buffer?
4630         if (ent->animcache_vertexmesh)
4631         {
4632                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4633                 for (i = 0;i < numvertices;i++)
4634                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4635                 if (ent->animcache_svector3f)
4636                         for (i = 0;i < numvertices;i++)
4637                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4638                 if (ent->animcache_tvector3f)
4639                         for (i = 0;i < numvertices;i++)
4640                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4641                 if (ent->animcache_normal3f)
4642                         for (i = 0;i < numvertices;i++)
4643                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4644                 // TODO: upload vertexmeshbuffer?
4645         }
4646 }
4647
4648 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4649 {
4650         dp_model_t *model = ent->model;
4651         int numvertices;
4652         // see if it's already cached this frame
4653         if (ent->animcache_vertex3f)
4654         {
4655                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4656                 if (wantnormals || wanttangents)
4657                 {
4658                         if (ent->animcache_normal3f)
4659                                 wantnormals = false;
4660                         if (ent->animcache_svector3f)
4661                                 wanttangents = false;
4662                         if (wantnormals || wanttangents)
4663                         {
4664                                 numvertices = model->surfmesh.num_vertices;
4665                                 if (wantnormals)
4666                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4667                                 if (wanttangents)
4668                                 {
4669                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4670                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4671                                 }
4672                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4673                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4674                         }
4675                 }
4676         }
4677         else
4678         {
4679                 // see if this ent is worth caching
4680                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4681                         return false;
4682                 // get some memory for this entity and generate mesh data
4683                 numvertices = model->surfmesh.num_vertices;
4684                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4685                 if (wantnormals)
4686                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4687                 if (wanttangents)
4688                 {
4689                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4690                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4691                 }
4692                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4693                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4694         }
4695         return true;
4696 }
4697
4698 void R_AnimCache_CacheVisibleEntities(void)
4699 {
4700         int i;
4701         qboolean wantnormals = true;
4702         qboolean wanttangents = !r_showsurfaces.integer;
4703
4704         switch(vid.renderpath)
4705         {
4706         case RENDERPATH_GL20:
4707         case RENDERPATH_D3D9:
4708         case RENDERPATH_D3D10:
4709         case RENDERPATH_D3D11:
4710         case RENDERPATH_GLES2:
4711                 break;
4712         case RENDERPATH_GL11:
4713         case RENDERPATH_GL13:
4714         case RENDERPATH_GLES1:
4715                 wanttangents = false;
4716                 break;
4717         case RENDERPATH_SOFT:
4718                 break;
4719         }
4720
4721         if (r_shownormals.integer)
4722                 wanttangents = wantnormals = true;
4723
4724         // TODO: thread this
4725         // NOTE: R_PrepareRTLights() also caches entities
4726
4727         for (i = 0;i < r_refdef.scene.numentities;i++)
4728                 if (r_refdef.viewcache.entityvisible[i])
4729                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4730 }
4731
4732 //==================================================================================
4733
4734 extern cvar_t r_overheadsprites_pushback;
4735
4736 static void R_View_UpdateEntityLighting (void)
4737 {
4738         int i;
4739         entity_render_t *ent;
4740         vec3_t tempdiffusenormal, avg;
4741         vec_t f, fa, fd, fdd;
4742         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4743
4744         for (i = 0;i < r_refdef.scene.numentities;i++)
4745         {
4746                 ent = r_refdef.scene.entities[i];
4747
4748                 // skip unseen models
4749                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4750                         continue;
4751
4752                 // skip bsp models
4753                 if (ent->model && ent->model == cl.worldmodel)
4754                 {
4755                         // TODO: use modellight for r_ambient settings on world?
4756                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4757                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4758                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4759                         continue;
4760                 }
4761                 
4762                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4763                 {
4764                         // aleady updated by CSQC
4765                         // TODO: force modellight on BSP models in this case?
4766                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
4767                 }
4768                 else
4769                 {
4770                         // fetch the lighting from the worldmodel data
4771                         VectorClear(ent->modellight_ambient);
4772                         VectorClear(ent->modellight_diffuse);
4773                         VectorClear(tempdiffusenormal);
4774                         if (ent->flags & RENDER_LIGHT)
4775                         {
4776                                 vec3_t org;
4777                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4778
4779                                 // complete lightning for lit sprites
4780                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4781                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4782                                 {
4783                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4784                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
4785                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4786                                 }
4787                                 else
4788                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4789
4790                                 if(ent->flags & RENDER_EQUALIZE)
4791                                 {
4792                                         // first fix up ambient lighting...
4793                                         if(r_equalize_entities_minambient.value > 0)
4794                                         {
4795                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4796                                                 if(fd > 0)
4797                                                 {
4798                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4799                                                         if(fa < r_equalize_entities_minambient.value * fd)
4800                                                         {
4801                                                                 // solve:
4802                                                                 //   fa'/fd' = minambient
4803                                                                 //   fa'+0.25*fd' = fa+0.25*fd
4804                                                                 //   ...
4805                                                                 //   fa' = fd' * minambient
4806                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
4807                                                                 //   ...
4808                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4809                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4810                                                                 //   ...
4811                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4812                                                                 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
4813                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4814                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4815                                                         }
4816                                                 }
4817                                         }
4818
4819                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4820                                         {
4821                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4822                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4823                                                 f = fa + 0.25 * fd;
4824                                                 if(f > 0)
4825                                                 {
4826                                                         // adjust brightness and saturation to target
4827                                                         avg[0] = avg[1] = avg[2] = fa / f;
4828                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4829                                                         avg[0] = avg[1] = avg[2] = fd / f;
4830                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4831                                                 }
4832                                         }
4833                                 }
4834                         }
4835                         else // highly rare
4836                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
4837                 }
4838
4839                 // move the light direction into modelspace coordinates for lighting code
4840                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4841                 if(VectorLength2(ent->modellight_lightdir) == 0)
4842                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4843                 VectorNormalize(ent->modellight_lightdir);
4844         }
4845 }
4846
4847 #define MAX_LINEOFSIGHTTRACES 64
4848
4849 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4850 {
4851         int i;
4852         vec3_t boxmins, boxmaxs;
4853         vec3_t start;
4854         vec3_t end;
4855         dp_model_t *model = r_refdef.scene.worldmodel;
4856
4857         if (!model || !model->brush.TraceLineOfSight)
4858                 return true;
4859
4860         // expand the box a little
4861         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4862         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4863         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4864         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4865         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4866         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4867
4868         // return true if eye is inside enlarged box
4869         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4870                 return true;
4871
4872         // try center
4873         VectorCopy(eye, start);
4874         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4875         if (model->brush.TraceLineOfSight(model, start, end))
4876                 return true;
4877
4878         // try various random positions
4879         for (i = 0;i < numsamples;i++)
4880         {
4881                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4882                 if (model->brush.TraceLineOfSight(model, start, end))
4883                         return true;
4884         }
4885
4886         return false;
4887 }
4888
4889
4890 static void R_View_UpdateEntityVisible (void)
4891 {
4892         int i;
4893         int renderimask;
4894         int samples;
4895         entity_render_t *ent;
4896
4897         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4898                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4899                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4900                 :                                                          RENDER_EXTERIORMODEL;
4901         if (!r_drawviewmodel.integer)
4902                 renderimask |= RENDER_VIEWMODEL;
4903         if (!r_drawexteriormodel.integer)
4904                 renderimask |= RENDER_EXTERIORMODEL;
4905         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4906         {
4907                 // worldmodel can check visibility
4908                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4909                 for (i = 0;i < r_refdef.scene.numentities;i++)
4910                 {
4911                         ent = r_refdef.scene.entities[i];
4912                         if (!(ent->flags & renderimask))
4913                         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)))
4914                         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))
4915                                 r_refdef.viewcache.entityvisible[i] = true;
4916                 }
4917         }
4918         else
4919         {
4920                 // no worldmodel or it can't check visibility
4921                 for (i = 0;i < r_refdef.scene.numentities;i++)
4922                 {
4923                         ent = r_refdef.scene.entities[i];
4924                         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));
4925                 }
4926         }
4927         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4928                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4929         {
4930                 for (i = 0;i < r_refdef.scene.numentities;i++)
4931                 {
4932                         if (!r_refdef.viewcache.entityvisible[i])
4933                                 continue;
4934                         ent = r_refdef.scene.entities[i];
4935                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4936                         {
4937                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4938                                 if (samples < 0)
4939                                         continue; // temp entities do pvs only
4940                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4941                                         ent->last_trace_visibility = realtime;
4942                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4943                                         r_refdef.viewcache.entityvisible[i] = 0;
4944                         }
4945                 }
4946         }
4947 }
4948
4949 /// only used if skyrendermasked, and normally returns false
4950 static int R_DrawBrushModelsSky (void)
4951 {
4952         int i, sky;
4953         entity_render_t *ent;
4954
4955         sky = false;
4956         for (i = 0;i < r_refdef.scene.numentities;i++)
4957         {
4958                 if (!r_refdef.viewcache.entityvisible[i])
4959                         continue;
4960                 ent = r_refdef.scene.entities[i];
4961                 if (!ent->model || !ent->model->DrawSky)
4962                         continue;
4963                 ent->model->DrawSky(ent);
4964                 sky = true;
4965         }
4966         return sky;
4967 }
4968
4969 static void R_DrawNoModel(entity_render_t *ent);
4970 static void R_DrawModels(void)
4971 {
4972         int i;
4973         entity_render_t *ent;
4974
4975         for (i = 0;i < r_refdef.scene.numentities;i++)
4976         {
4977                 if (!r_refdef.viewcache.entityvisible[i])
4978                         continue;
4979                 ent = r_refdef.scene.entities[i];
4980                 r_refdef.stats.entities++;
4981                 /*
4982                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4983                 {
4984                         vec3_t f, l, u, o;
4985                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4986                         Con_Printf("R_DrawModels\n");
4987                         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]);
4988                         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);
4989                         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);
4990                 }
4991                 */
4992                 if (ent->model && ent->model->Draw != NULL)
4993                         ent->model->Draw(ent);
4994                 else
4995                         R_DrawNoModel(ent);
4996         }
4997 }
4998
4999 static void R_DrawModelsDepth(void)
5000 {
5001         int i;
5002         entity_render_t *ent;
5003
5004         for (i = 0;i < r_refdef.scene.numentities;i++)
5005         {
5006                 if (!r_refdef.viewcache.entityvisible[i])
5007                         continue;
5008                 ent = r_refdef.scene.entities[i];
5009                 if (ent->model && ent->model->DrawDepth != NULL)
5010                         ent->model->DrawDepth(ent);
5011         }
5012 }
5013
5014 static void R_DrawModelsDebug(void)
5015 {
5016         int i;
5017         entity_render_t *ent;
5018
5019         for (i = 0;i < r_refdef.scene.numentities;i++)
5020         {
5021                 if (!r_refdef.viewcache.entityvisible[i])
5022                         continue;
5023                 ent = r_refdef.scene.entities[i];
5024                 if (ent->model && ent->model->DrawDebug != NULL)
5025                         ent->model->DrawDebug(ent);
5026         }
5027 }
5028
5029 static void R_DrawModelsAddWaterPlanes(void)
5030 {
5031         int i;
5032         entity_render_t *ent;
5033
5034         for (i = 0;i < r_refdef.scene.numentities;i++)
5035         {
5036                 if (!r_refdef.viewcache.entityvisible[i])
5037                         continue;
5038                 ent = r_refdef.scene.entities[i];
5039                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5040                         ent->model->DrawAddWaterPlanes(ent);
5041         }
5042 }
5043
5044 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}};
5045
5046 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5047 {
5048         if (r_hdr_irisadaptation.integer)
5049         {
5050                 vec3_t p;
5051                 vec3_t ambient;
5052                 vec3_t diffuse;
5053                 vec3_t diffusenormal;
5054                 vec3_t forward;
5055                 vec_t brightness = 0.0f;
5056                 vec_t goal;
5057                 vec_t current;
5058                 vec_t d;
5059                 int c;
5060                 VectorCopy(r_refdef.view.forward, forward);
5061                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5062                 {
5063                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5064                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5065                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5066                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5067                         d = DotProduct(forward, diffusenormal);
5068                         brightness += VectorLength(ambient);
5069                         if (d > 0)
5070                                 brightness += d * VectorLength(diffuse);
5071                 }
5072                 brightness *= 1.0f / c;
5073                 brightness += 0.00001f; // make sure it's never zero
5074                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5075                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5076                 current = r_hdr_irisadaptation_value.value;
5077                 if (current < goal)
5078                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5079                 else if (current > goal)
5080                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5081                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5082                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5083         }
5084         else if (r_hdr_irisadaptation_value.value != 1.0f)
5085                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5086 }
5087
5088 static void R_View_SetFrustum(const int *scissor)
5089 {
5090         int i;
5091         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5092         vec3_t forward, left, up, origin, v;
5093
5094         if(scissor)
5095         {
5096                 // flipped x coordinates (because x points left here)
5097                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5098                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5099
5100                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5101                 switch(vid.renderpath)
5102                 {
5103                         case RENDERPATH_D3D9:
5104                         case RENDERPATH_D3D10:
5105                         case RENDERPATH_D3D11:
5106                                 // non-flipped y coordinates
5107                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5108                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5109                                 break;
5110                         case RENDERPATH_SOFT:
5111                         case RENDERPATH_GL11:
5112                         case RENDERPATH_GL13:
5113                         case RENDERPATH_GL20:
5114                         case RENDERPATH_GLES1:
5115                         case RENDERPATH_GLES2:
5116                                 // non-flipped y coordinates
5117                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5118                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5119                                 break;
5120                 }
5121         }
5122
5123         // we can't trust r_refdef.view.forward and friends in reflected scenes
5124         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5125
5126 #if 0
5127         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5128         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5129         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5130         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5131         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5132         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5133         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5134         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5135         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5136         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5137         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5138         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5139 #endif
5140
5141 #if 0
5142         zNear = r_refdef.nearclip;
5143         nudge = 1.0 - 1.0 / (1<<23);
5144         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5145         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5146         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5147         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5148         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5149         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5150         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5151         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5152 #endif
5153
5154
5155
5156 #if 0
5157         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5158         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5159         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5160         r_refdef.view.frustum[0].dist = m[15] - m[12];
5161
5162         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5163         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5164         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5165         r_refdef.view.frustum[1].dist = m[15] + m[12];
5166
5167         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5168         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5169         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5170         r_refdef.view.frustum[2].dist = m[15] - m[13];
5171
5172         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5173         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5174         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5175         r_refdef.view.frustum[3].dist = m[15] + m[13];
5176
5177         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5178         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5179         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5180         r_refdef.view.frustum[4].dist = m[15] - m[14];
5181
5182         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5183         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5184         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5185         r_refdef.view.frustum[5].dist = m[15] + m[14];
5186 #endif
5187
5188         if (r_refdef.view.useperspective)
5189         {
5190                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5191                 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]);
5192                 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]);
5193                 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]);
5194                 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]);
5195
5196                 // then the normals from the corners relative to origin
5197                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5198                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5199                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5200                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5201
5202                 // in a NORMAL view, forward cross left == up
5203                 // in a REFLECTED view, forward cross left == down
5204                 // so our cross products above need to be adjusted for a left handed coordinate system
5205                 CrossProduct(forward, left, v);
5206                 if(DotProduct(v, up) < 0)
5207                 {
5208                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5209                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5210                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5211                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5212                 }
5213
5214                 // Leaving those out was a mistake, those were in the old code, and they
5215                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5216                 // I couldn't reproduce it after adding those normalizations. --blub
5217                 VectorNormalize(r_refdef.view.frustum[0].normal);
5218                 VectorNormalize(r_refdef.view.frustum[1].normal);
5219                 VectorNormalize(r_refdef.view.frustum[2].normal);
5220                 VectorNormalize(r_refdef.view.frustum[3].normal);
5221
5222                 // make the corners absolute
5223                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5224                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5225                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5226                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5227
5228                 // one more normal
5229                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5230
5231                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5232                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5233                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5234                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5235                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5236         }
5237         else
5238         {
5239                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5240                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5241                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5242                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5243                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5244                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5245                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5246                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5247                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5248                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5249         }
5250         r_refdef.view.numfrustumplanes = 5;
5251
5252         if (r_refdef.view.useclipplane)
5253         {
5254                 r_refdef.view.numfrustumplanes = 6;
5255                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5256         }
5257
5258         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5259                 PlaneClassify(r_refdef.view.frustum + i);
5260
5261         // LordHavoc: note to all quake engine coders, Quake had a special case
5262         // for 90 degrees which assumed a square view (wrong), so I removed it,
5263         // Quake2 has it disabled as well.
5264
5265         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5266         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5267         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5268         //PlaneClassify(&frustum[0]);
5269
5270         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5271         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5272         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5273         //PlaneClassify(&frustum[1]);
5274
5275         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5276         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5277         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5278         //PlaneClassify(&frustum[2]);
5279
5280         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5281         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5282         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5283         //PlaneClassify(&frustum[3]);
5284
5285         // nearclip plane
5286         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5287         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5288         //PlaneClassify(&frustum[4]);
5289 }
5290
5291 static void R_View_UpdateWithScissor(const int *myscissor)
5292 {
5293         R_Main_ResizeViewCache();
5294         R_View_SetFrustum(myscissor);
5295         R_View_WorldVisibility(r_refdef.view.useclipplane);
5296         R_View_UpdateEntityVisible();
5297         R_View_UpdateEntityLighting();
5298 }
5299
5300 static void R_View_Update(void)
5301 {
5302         R_Main_ResizeViewCache();
5303         R_View_SetFrustum(NULL);
5304         R_View_WorldVisibility(r_refdef.view.useclipplane);
5305         R_View_UpdateEntityVisible();
5306         R_View_UpdateEntityLighting();
5307 }
5308
5309 float viewscalefpsadjusted = 1.0f;
5310
5311 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5312 {
5313         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5314         scale = bound(0.03125f, scale, 1.0f);
5315         *outwidth = (int)ceil(width * scale);
5316         *outheight = (int)ceil(height * scale);
5317 }
5318
5319 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5320 {
5321         const float *customclipplane = NULL;
5322         float plane[4];
5323         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5324         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5325         {
5326                 // LordHavoc: couldn't figure out how to make this approach the
5327                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5328                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5329                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5330                         dist = r_refdef.view.clipplane.dist;
5331                 plane[0] = r_refdef.view.clipplane.normal[0];
5332                 plane[1] = r_refdef.view.clipplane.normal[1];
5333                 plane[2] = r_refdef.view.clipplane.normal[2];
5334                 plane[3] = -dist;
5335                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5336         }
5337
5338         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5339         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5340
5341         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5342         if (!r_refdef.view.useperspective)
5343                 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);
5344         else if (vid.stencil && r_useinfinitefarclip.integer)
5345                 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);
5346         else
5347                 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);
5348         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5349         R_SetViewport(&r_refdef.view.viewport);
5350         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5351         {
5352                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5353                 float screenplane[4];
5354                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5355                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5356                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5357                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5358                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5359         }
5360 }
5361
5362 void R_EntityMatrix(const matrix4x4_t *matrix)
5363 {
5364         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5365         {
5366                 gl_modelmatrixchanged = false;
5367                 gl_modelmatrix = *matrix;
5368                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5369                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5370                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5371                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5372                 CHECKGLERROR
5373                 switch(vid.renderpath)
5374                 {
5375                 case RENDERPATH_D3D9:
5376 #ifdef SUPPORTD3D
5377                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5378                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5379 #endif
5380                         break;
5381                 case RENDERPATH_D3D10:
5382                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5383                         break;
5384                 case RENDERPATH_D3D11:
5385                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5386                         break;
5387                 case RENDERPATH_GL11:
5388                 case RENDERPATH_GL13:
5389                 case RENDERPATH_GLES1:
5390                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5391                         break;
5392                 case RENDERPATH_SOFT:
5393                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5394                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5395                         break;
5396                 case RENDERPATH_GL20:
5397                 case RENDERPATH_GLES2:
5398                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5399                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5400                         break;
5401                 }
5402         }
5403 }
5404
5405 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5406 {
5407         r_viewport_t viewport;
5408
5409         CHECKGLERROR
5410
5411         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5412         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);
5413         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5414         R_SetViewport(&viewport);
5415         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5416         GL_Color(1, 1, 1, 1);
5417         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5418         GL_BlendFunc(GL_ONE, GL_ZERO);
5419         GL_ScissorTest(false);
5420         GL_DepthMask(false);
5421         GL_DepthRange(0, 1);
5422         GL_DepthTest(false);
5423         GL_DepthFunc(GL_LEQUAL);
5424         R_EntityMatrix(&identitymatrix);
5425         R_Mesh_ResetTextureState();
5426         GL_PolygonOffset(0, 0);
5427         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5428         switch(vid.renderpath)
5429         {
5430         case RENDERPATH_GL11:
5431         case RENDERPATH_GL13:
5432         case RENDERPATH_GL20:
5433         case RENDERPATH_GLES1:
5434         case RENDERPATH_GLES2:
5435                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5436                 break;
5437         case RENDERPATH_D3D9:
5438         case RENDERPATH_D3D10:
5439         case RENDERPATH_D3D11:
5440         case RENDERPATH_SOFT:
5441                 break;
5442         }
5443         GL_CullFace(GL_NONE);
5444
5445         CHECKGLERROR
5446 }
5447
5448 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5449 {
5450         DrawQ_Finish();
5451
5452         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5453 }
5454
5455 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5456 {
5457         DrawQ_Finish();
5458
5459         R_SetupView(true, fbo, depthtexture, colortexture);
5460         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5461         GL_Color(1, 1, 1, 1);
5462         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5463         GL_BlendFunc(GL_ONE, GL_ZERO);
5464         GL_ScissorTest(true);
5465         GL_DepthMask(true);
5466         GL_DepthRange(0, 1);
5467         GL_DepthTest(true);
5468         GL_DepthFunc(GL_LEQUAL);
5469         R_EntityMatrix(&identitymatrix);
5470         R_Mesh_ResetTextureState();
5471         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5472         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5473         switch(vid.renderpath)
5474         {
5475         case RENDERPATH_GL11:
5476         case RENDERPATH_GL13:
5477         case RENDERPATH_GL20:
5478         case RENDERPATH_GLES1:
5479         case RENDERPATH_GLES2:
5480                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5481                 break;
5482         case RENDERPATH_D3D9:
5483         case RENDERPATH_D3D10:
5484         case RENDERPATH_D3D11:
5485         case RENDERPATH_SOFT:
5486                 break;
5487         }
5488         GL_CullFace(r_refdef.view.cullface_back);
5489 }
5490
5491 /*
5492 ================
5493 R_RenderView_UpdateViewVectors
5494 ================
5495 */
5496 void R_RenderView_UpdateViewVectors(void)
5497 {
5498         // break apart the view matrix into vectors for various purposes
5499         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5500         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5501         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5502         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5503         // make an inverted copy of the view matrix for tracking sprites
5504         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5505 }
5506
5507 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5508 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5509
5510 static void R_Water_StartFrame(void)
5511 {
5512         int i;
5513         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5514         r_waterstate_waterplane_t *p;
5515         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5516
5517         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5518                 return;
5519
5520         switch(vid.renderpath)
5521         {
5522         case RENDERPATH_GL20:
5523         case RENDERPATH_D3D9:
5524         case RENDERPATH_D3D10:
5525         case RENDERPATH_D3D11:
5526         case RENDERPATH_SOFT:
5527         case RENDERPATH_GLES2:
5528                 break;
5529         case RENDERPATH_GL11:
5530         case RENDERPATH_GL13:
5531         case RENDERPATH_GLES1:
5532                 return;
5533         }
5534
5535         // set waterwidth and waterheight to the water resolution that will be
5536         // used (often less than the screen resolution for faster rendering)
5537         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5538
5539         // calculate desired texture sizes
5540         // can't use water if the card does not support the texture size
5541         if (!r_water.integer || r_showsurfaces.integer)
5542                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5543         else if (vid.support.arb_texture_non_power_of_two)
5544         {
5545                 texturewidth = waterwidth;
5546                 textureheight = waterheight;
5547                 camerawidth = waterwidth;
5548                 cameraheight = waterheight;
5549         }
5550         else
5551         {
5552                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5553                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5554                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5555                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5556         }
5557
5558         // allocate textures as needed
5559         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))
5560         {
5561                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5562                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5563                 {
5564                         if (p->texture_refraction)
5565                                 R_FreeTexture(p->texture_refraction);
5566                         p->texture_refraction = NULL;
5567                         if (p->fbo_refraction)
5568                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5569                         p->fbo_refraction = 0;
5570                         if (p->texture_reflection)
5571                                 R_FreeTexture(p->texture_reflection);
5572                         p->texture_reflection = NULL;
5573                         if (p->fbo_reflection)
5574                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5575                         p->fbo_reflection = 0;
5576                         if (p->texture_camera)
5577                                 R_FreeTexture(p->texture_camera);
5578                         p->texture_camera = NULL;
5579                         if (p->fbo_camera)
5580                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5581                         p->fbo_camera = 0;
5582                 }
5583                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5584                 r_fb.water.texturewidth = texturewidth;
5585                 r_fb.water.textureheight = textureheight;
5586                 r_fb.water.camerawidth = camerawidth;
5587                 r_fb.water.cameraheight = cameraheight;
5588         }
5589
5590         if (r_fb.water.texturewidth)
5591         {
5592                 int scaledwidth, scaledheight;
5593
5594                 r_fb.water.enabled = true;
5595
5596                 // water resolution is usually reduced
5597                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5598                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5599                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5600
5601                 // set up variables that will be used in shader setup
5602                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5603                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5604                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5605                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5606         }
5607
5608         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5609         r_fb.water.numwaterplanes = 0;
5610 }
5611
5612 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5613 {
5614         int planeindex, bestplaneindex, vertexindex;
5615         vec3_t mins, maxs, normal, center, v, n;
5616         vec_t planescore, bestplanescore;
5617         mplane_t plane;
5618         r_waterstate_waterplane_t *p;
5619         texture_t *t = R_GetCurrentTexture(surface->texture);
5620
5621         rsurface.texture = t;
5622         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5623         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5624         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5625                 return;
5626         // average the vertex normals, find the surface bounds (after deformvertexes)
5627         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5628         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5629         VectorCopy(n, normal);
5630         VectorCopy(v, mins);
5631         VectorCopy(v, maxs);
5632         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5633         {
5634                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5635                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5636                 VectorAdd(normal, n, normal);
5637                 mins[0] = min(mins[0], v[0]);
5638                 mins[1] = min(mins[1], v[1]);
5639                 mins[2] = min(mins[2], v[2]);
5640                 maxs[0] = max(maxs[0], v[0]);
5641                 maxs[1] = max(maxs[1], v[1]);
5642                 maxs[2] = max(maxs[2], v[2]);
5643         }
5644         VectorNormalize(normal);
5645         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5646
5647         VectorCopy(normal, plane.normal);
5648         VectorNormalize(plane.normal);
5649         plane.dist = DotProduct(center, plane.normal);
5650         PlaneClassify(&plane);
5651         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5652         {
5653                 // skip backfaces (except if nocullface is set)
5654 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5655 //                      return;
5656                 VectorNegate(plane.normal, plane.normal);
5657                 plane.dist *= -1;
5658                 PlaneClassify(&plane);
5659         }
5660
5661
5662         // find a matching plane if there is one
5663         bestplaneindex = -1;
5664         bestplanescore = 1048576.0f;
5665         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5666         {
5667                 if(p->camera_entity == t->camera_entity)
5668                 {
5669                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5670                         if (bestplaneindex < 0 || bestplanescore > planescore)
5671                         {
5672                                 bestplaneindex = planeindex;
5673                                 bestplanescore = planescore;
5674                         }
5675                 }
5676         }
5677         planeindex = bestplaneindex;
5678         p = r_fb.water.waterplanes + planeindex;
5679
5680         // if this surface does not fit any known plane rendered this frame, add one
5681         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5682         {
5683                 // store the new plane
5684                 planeindex = r_fb.water.numwaterplanes++;
5685                 p = r_fb.water.waterplanes + planeindex;
5686                 p->plane = plane;
5687                 // clear materialflags and pvs
5688                 p->materialflags = 0;
5689                 p->pvsvalid = false;
5690                 p->camera_entity = t->camera_entity;
5691                 VectorCopy(mins, p->mins);
5692                 VectorCopy(maxs, p->maxs);
5693         }
5694         else
5695         {
5696                 // merge mins/maxs when we're adding this surface to the plane
5697                 p->mins[0] = min(p->mins[0], mins[0]);
5698                 p->mins[1] = min(p->mins[1], mins[1]);
5699                 p->mins[2] = min(p->mins[2], mins[2]);
5700                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5701                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5702                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5703         }
5704         // merge this surface's materialflags into the waterplane
5705         p->materialflags |= t->currentmaterialflags;
5706         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5707         {
5708                 // merge this surface's PVS into the waterplane
5709                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5710                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5711                 {
5712                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5713                         p->pvsvalid = true;
5714                 }
5715         }
5716 }
5717
5718 extern cvar_t r_drawparticles;
5719 extern cvar_t r_drawdecals;
5720
5721 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5722 {
5723         int myscissor[4];
5724         r_refdef_view_t originalview;
5725         r_refdef_view_t myview;
5726         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;
5727         r_waterstate_waterplane_t *p;
5728         vec3_t visorigin;
5729         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5730         char vabuf[1024];
5731
5732         originalview = r_refdef.view;
5733
5734         // lowquality hack, temporarily shut down some cvars and restore afterwards
5735         qualityreduction = r_water_lowquality.integer;
5736         if (qualityreduction > 0)
5737         {
5738                 if (qualityreduction >= 1)
5739                 {
5740                         old_r_shadows = r_shadows.integer;
5741                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5742                         old_r_dlight = r_shadow_realtime_dlight.integer;
5743                         Cvar_SetValueQuick(&r_shadows, 0);
5744                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5745                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5746                 }
5747                 if (qualityreduction >= 2)
5748                 {
5749                         old_r_dynamic = r_dynamic.integer;
5750                         old_r_particles = r_drawparticles.integer;
5751                         old_r_decals = r_drawdecals.integer;
5752                         Cvar_SetValueQuick(&r_dynamic, 0);
5753                         Cvar_SetValueQuick(&r_drawparticles, 0);
5754                         Cvar_SetValueQuick(&r_drawdecals, 0);
5755                 }
5756         }
5757
5758         // make sure enough textures are allocated
5759         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5760         {
5761                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5762                 {
5763                         if (!p->texture_refraction)
5764                                 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);
5765                         if (!p->texture_refraction)
5766                                 goto error;
5767                         if (usewaterfbo)
5768                         {
5769                                 if (r_fb.water.depthtexture == NULL)
5770                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5771                                 if (p->fbo_refraction == 0)
5772                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5773                         }
5774                 }
5775                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5776                 {
5777                         if (!p->texture_camera)
5778                                 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);
5779                         if (!p->texture_camera)
5780                                 goto error;
5781                         if (usewaterfbo)
5782                         {
5783                                 if (r_fb.water.depthtexture == NULL)
5784                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5785                                 if (p->fbo_camera == 0)
5786                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5787                         }
5788                 }
5789
5790                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5791                 {
5792                         if (!p->texture_reflection)
5793                                 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);
5794                         if (!p->texture_reflection)
5795                                 goto error;
5796                         if (usewaterfbo)
5797                         {
5798                                 if (r_fb.water.depthtexture == NULL)
5799                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5800                                 if (p->fbo_reflection == 0)
5801                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5802                         }
5803                 }
5804         }
5805
5806         // render views
5807         r_refdef.view = originalview;
5808         r_refdef.view.showdebug = false;
5809         r_refdef.view.width = r_fb.water.waterwidth;
5810         r_refdef.view.height = r_fb.water.waterheight;
5811         r_refdef.view.useclipplane = true;
5812         myview = r_refdef.view;
5813         r_fb.water.renderingscene = true;
5814         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5815         {
5816                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5817                 {
5818                         r_refdef.view = myview;
5819                         if(r_water_scissormode.integer)
5820                         {
5821                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5822                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5823                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5824                         }
5825
5826                         // render reflected scene and copy into texture
5827                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5828                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5829                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5830                         r_refdef.view.clipplane = p->plane;
5831                         // reverse the cullface settings for this render
5832                         r_refdef.view.cullface_front = GL_FRONT;
5833                         r_refdef.view.cullface_back = GL_BACK;
5834                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5835                         {
5836                                 r_refdef.view.usecustompvs = true;
5837                                 if (p->pvsvalid)
5838                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5839                                 else
5840                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5841                         }
5842
5843                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5844                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5845                         R_ClearScreen(r_refdef.fogenabled);
5846                         if(r_water_scissormode.integer & 2)
5847                                 R_View_UpdateWithScissor(myscissor);
5848                         else
5849                                 R_View_Update();
5850                         R_AnimCache_CacheVisibleEntities();
5851                         if(r_water_scissormode.integer & 1)
5852                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5853                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5854
5855                         if (!p->fbo_reflection)
5856                                 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);
5857                         r_fb.water.hideplayer = false;
5858                 }
5859
5860                 // render the normal view scene and copy into texture
5861                 // (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)
5862                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5863                 {
5864                         r_refdef.view = myview;
5865                         if(r_water_scissormode.integer)
5866                         {
5867                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5868                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5869                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5870                         }
5871
5872                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5873
5874                         r_refdef.view.clipplane = p->plane;
5875                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5876                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5877
5878                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5879                         {
5880                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5881                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5882                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5883                                 R_RenderView_UpdateViewVectors();
5884                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5885                                 {
5886                                         r_refdef.view.usecustompvs = true;
5887                                         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);
5888                                 }
5889                         }
5890
5891                         PlaneClassify(&r_refdef.view.clipplane);
5892
5893                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5894                         R_ClearScreen(r_refdef.fogenabled);
5895                         if(r_water_scissormode.integer & 2)
5896                                 R_View_UpdateWithScissor(myscissor);
5897                         else
5898                                 R_View_Update();
5899                         R_AnimCache_CacheVisibleEntities();
5900                         if(r_water_scissormode.integer & 1)
5901                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5902                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5903
5904                         if (!p->fbo_refraction)
5905                                 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);
5906                         r_fb.water.hideplayer = false;
5907                 }
5908                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5909                 {
5910                         r_refdef.view = myview;
5911
5912                         r_refdef.view.clipplane = p->plane;
5913                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5914                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5915
5916                         r_refdef.view.width = r_fb.water.camerawidth;
5917                         r_refdef.view.height = r_fb.water.cameraheight;
5918                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5919                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5920                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5921                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5922
5923                         if(p->camera_entity)
5924                         {
5925                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5926                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5927                         }
5928
5929                         // note: all of the view is used for displaying... so
5930                         // there is no use in scissoring
5931
5932                         // reverse the cullface settings for this render
5933                         r_refdef.view.cullface_front = GL_FRONT;
5934                         r_refdef.view.cullface_back = GL_BACK;
5935                         // also reverse the view matrix
5936                         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
5937                         R_RenderView_UpdateViewVectors();
5938                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5939                         {
5940                                 r_refdef.view.usecustompvs = true;
5941                                 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);
5942                         }
5943                         
5944                         // camera needs no clipplane
5945                         r_refdef.view.useclipplane = false;
5946
5947                         PlaneClassify(&r_refdef.view.clipplane);
5948
5949                         r_fb.water.hideplayer = false;
5950
5951                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5952                         R_ClearScreen(r_refdef.fogenabled);
5953                         R_View_Update();
5954                         R_AnimCache_CacheVisibleEntities();
5955                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5956
5957                         if (!p->fbo_camera)
5958                                 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);
5959                         r_fb.water.hideplayer = false;
5960                 }
5961
5962         }
5963         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5964         r_fb.water.renderingscene = false;
5965         r_refdef.view = originalview;
5966         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5967         if (!r_fb.water.depthtexture)
5968                 R_ClearScreen(r_refdef.fogenabled);
5969         R_View_Update();
5970         R_AnimCache_CacheVisibleEntities();
5971         goto finish;
5972 error:
5973         r_refdef.view = originalview;
5974         r_fb.water.renderingscene = false;
5975         Cvar_SetValueQuick(&r_water, 0);
5976         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5977 finish:
5978         // lowquality hack, restore cvars
5979         if (qualityreduction > 0)
5980         {
5981                 if (qualityreduction >= 1)
5982                 {
5983                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5984                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5985                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5986                 }
5987                 if (qualityreduction >= 2)
5988                 {
5989                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5990                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5991                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5992                 }
5993         }
5994 }
5995
5996 static void R_Bloom_StartFrame(void)
5997 {
5998         int i;
5999         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
6000         int viewwidth, viewheight;
6001         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
6002         textype_t textype = TEXTYPE_COLORBUFFER;
6003
6004         switch (vid.renderpath)
6005         {
6006         case RENDERPATH_GL20:
6007                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6008                 if (vid.support.ext_framebuffer_object)
6009                 {
6010                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6011                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6012                 }
6013                 break;
6014         case RENDERPATH_GL11:
6015         case RENDERPATH_GL13:
6016         case RENDERPATH_GLES1:
6017         case RENDERPATH_GLES2:
6018         case RENDERPATH_D3D9:
6019         case RENDERPATH_D3D10:
6020         case RENDERPATH_D3D11:
6021                 r_fb.usedepthtextures = false;
6022                 break;
6023         case RENDERPATH_SOFT:
6024                 r_fb.usedepthtextures = true;
6025                 break;
6026         }
6027
6028         if (r_viewscale_fpsscaling.integer)
6029         {
6030                 double actualframetime;
6031                 double targetframetime;
6032                 double adjust;
6033                 actualframetime = r_refdef.lastdrawscreentime;
6034                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6035                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6036                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6037                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6038                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6039                 viewscalefpsadjusted += adjust;
6040                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6041         }
6042         else
6043                 viewscalefpsadjusted = 1.0f;
6044
6045         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6046
6047         switch(vid.renderpath)
6048         {
6049         case RENDERPATH_GL20:
6050         case RENDERPATH_D3D9:
6051         case RENDERPATH_D3D10:
6052         case RENDERPATH_D3D11:
6053         case RENDERPATH_SOFT:
6054         case RENDERPATH_GLES2:
6055                 break;
6056         case RENDERPATH_GL11:
6057         case RENDERPATH_GL13:
6058         case RENDERPATH_GLES1:
6059                 return;
6060         }
6061
6062         // set bloomwidth and bloomheight to the bloom resolution that will be
6063         // used (often less than the screen resolution for faster rendering)
6064         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6065         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6066         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6067         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6068         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6069
6070         // calculate desired texture sizes
6071         if (vid.support.arb_texture_non_power_of_two)
6072         {
6073                 screentexturewidth = vid.width;
6074                 screentextureheight = vid.height;
6075                 bloomtexturewidth = r_fb.bloomwidth;
6076                 bloomtextureheight = r_fb.bloomheight;
6077         }
6078         else
6079         {
6080                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6081                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6082                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6083                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6084         }
6085
6086         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))
6087         {
6088                 Cvar_SetValueQuick(&r_bloom, 0);
6089                 Cvar_SetValueQuick(&r_motionblur, 0);
6090                 Cvar_SetValueQuick(&r_damageblur, 0);
6091         }
6092
6093         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6094          && !r_bloom.integer
6095          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6096          && !useviewfbo
6097          && r_viewscale.value == 1.0f
6098          && !r_viewscale_fpsscaling.integer)
6099                 screentexturewidth = screentextureheight = 0;
6100         if (!r_bloom.integer)
6101                 bloomtexturewidth = bloomtextureheight = 0;
6102
6103         // allocate textures as needed
6104         if (r_fb.screentexturewidth != screentexturewidth
6105          || r_fb.screentextureheight != screentextureheight
6106          || r_fb.bloomtexturewidth != bloomtexturewidth
6107          || r_fb.bloomtextureheight != bloomtextureheight
6108          || r_fb.textype != textype
6109          || useviewfbo != (r_fb.fbo != 0))
6110         {
6111                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6112                 {
6113                         if (r_fb.bloomtexture[i])
6114                                 R_FreeTexture(r_fb.bloomtexture[i]);
6115                         r_fb.bloomtexture[i] = NULL;
6116
6117                         if (r_fb.bloomfbo[i])
6118                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6119                         r_fb.bloomfbo[i] = 0;
6120                 }
6121
6122                 if (r_fb.fbo)
6123                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6124                 r_fb.fbo = 0;
6125
6126                 if (r_fb.colortexture)
6127                         R_FreeTexture(r_fb.colortexture);
6128                 r_fb.colortexture = NULL;
6129
6130                 if (r_fb.depthtexture)
6131                         R_FreeTexture(r_fb.depthtexture);
6132                 r_fb.depthtexture = NULL;
6133
6134                 if (r_fb.ghosttexture)
6135                         R_FreeTexture(r_fb.ghosttexture);
6136                 r_fb.ghosttexture = NULL;
6137
6138                 r_fb.screentexturewidth = screentexturewidth;
6139                 r_fb.screentextureheight = screentextureheight;
6140                 r_fb.bloomtexturewidth = bloomtexturewidth;
6141                 r_fb.bloomtextureheight = bloomtextureheight;
6142                 r_fb.textype = textype;
6143
6144                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6145                 {
6146                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6147                                 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);
6148                         r_fb.ghosttexture_valid = false;
6149                         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);
6150                         if (useviewfbo)
6151                         {
6152                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6153                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6154                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6155                         }
6156                 }
6157
6158                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6159                 {
6160                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6161                         {
6162                                 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);
6163                                 if (useviewfbo)
6164                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6165                         }
6166                 }
6167         }
6168
6169         // bloom texture is a different resolution
6170         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6171         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6172         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6173         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6174         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6175
6176         // set up a texcoord array for the full resolution screen image
6177         // (we have to keep this around to copy back during final render)
6178         r_fb.screentexcoord2f[0] = 0;
6179         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6180         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6181         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6182         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6183         r_fb.screentexcoord2f[5] = 0;
6184         r_fb.screentexcoord2f[6] = 0;
6185         r_fb.screentexcoord2f[7] = 0;
6186
6187         if(r_fb.fbo) 
6188         {
6189                 for (i = 1;i < 8;i += 2)
6190                 {
6191                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6192                 }
6193         }
6194
6195         // set up a texcoord array for the reduced resolution bloom image
6196         // (which will be additive blended over the screen image)
6197         r_fb.bloomtexcoord2f[0] = 0;
6198         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6199         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6200         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6201         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6202         r_fb.bloomtexcoord2f[5] = 0;
6203         r_fb.bloomtexcoord2f[6] = 0;
6204         r_fb.bloomtexcoord2f[7] = 0;
6205
6206         switch(vid.renderpath)
6207         {
6208         case RENDERPATH_GL11:
6209         case RENDERPATH_GL13:
6210         case RENDERPATH_GL20:
6211         case RENDERPATH_SOFT:
6212         case RENDERPATH_GLES1:
6213         case RENDERPATH_GLES2:
6214                 break;
6215         case RENDERPATH_D3D9:
6216         case RENDERPATH_D3D10:
6217         case RENDERPATH_D3D11:
6218                 for (i = 0;i < 4;i++)
6219                 {
6220                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6221                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6222                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6223                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6224                 }
6225                 break;
6226         }
6227
6228         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6229
6230         if (r_fb.fbo)
6231                 r_refdef.view.clear = true;
6232 }
6233
6234 static void R_Bloom_MakeTexture(void)
6235 {
6236         int x, range, dir;
6237         float xoffset, yoffset, r, brighten;
6238         rtexture_t *intex;
6239         float colorscale = r_bloom_colorscale.value;
6240
6241         r_refdef.stats.bloom++;
6242     
6243 #if 0
6244     // this copy is unnecessary since it happens in R_BlendView already
6245         if (!r_fb.fbo)
6246         {
6247                 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);
6248                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6249         }
6250 #endif
6251
6252         // scale down screen texture to the bloom texture size
6253         CHECKGLERROR
6254         r_fb.bloomindex = 0;
6255         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6256         R_SetViewport(&r_fb.bloomviewport);
6257         GL_DepthTest(false);
6258         GL_BlendFunc(GL_ONE, GL_ZERO);
6259         GL_Color(colorscale, colorscale, colorscale, 1);
6260         // 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...
6261         switch(vid.renderpath)
6262         {
6263         case RENDERPATH_GL11:
6264         case RENDERPATH_GL13:
6265         case RENDERPATH_GL20:
6266         case RENDERPATH_GLES1:
6267         case RENDERPATH_GLES2:
6268         case RENDERPATH_SOFT:
6269                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6270                 break;
6271         case RENDERPATH_D3D9:
6272         case RENDERPATH_D3D10:
6273         case RENDERPATH_D3D11:
6274                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6275                 break;
6276         }
6277         // TODO: do boxfilter scale-down in shader?
6278         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6279         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6280         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6281
6282         // we now have a properly scaled bloom image
6283         if (!r_fb.bloomfbo[r_fb.bloomindex])
6284         {
6285                 // copy it into the bloom texture
6286                 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);
6287                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6288         }
6289
6290         // multiply bloom image by itself as many times as desired
6291         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6292         {
6293                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6294                 r_fb.bloomindex ^= 1;
6295                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6296                 x *= 2;
6297                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6298                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6299                 {
6300                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6301                         GL_Color(r,r,r,1); // apply fix factor
6302                 }
6303                 else
6304                 {
6305                         if(x <= 2)
6306                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6307                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6308                         GL_Color(1,1,1,1); // no fix factor supported here
6309                 }
6310                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6311                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6312                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6313                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6314
6315                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6316                 {
6317                         // copy the darkened image to a texture
6318                         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);
6319                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6320                 }
6321         }
6322
6323         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6324         brighten = r_bloom_brighten.value;
6325         brighten = sqrt(brighten);
6326         if(range >= 1)
6327                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6328
6329         for (dir = 0;dir < 2;dir++)
6330         {
6331                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6332                 r_fb.bloomindex ^= 1;
6333                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6334                 // blend on at multiple vertical offsets to achieve a vertical blur
6335                 // TODO: do offset blends using GLSL
6336                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6337                 GL_BlendFunc(GL_ONE, GL_ZERO);
6338                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6339                 for (x = -range;x <= range;x++)
6340                 {
6341                         if (!dir){xoffset = 0;yoffset = x;}
6342                         else {xoffset = x;yoffset = 0;}
6343                         xoffset /= (float)r_fb.bloomtexturewidth;
6344                         yoffset /= (float)r_fb.bloomtextureheight;
6345                         // compute a texcoord array with the specified x and y offset
6346                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6347                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6348                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6349                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6350                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6351                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6352                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6353                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6354                         // this r value looks like a 'dot' particle, fading sharply to
6355                         // black at the edges
6356                         // (probably not realistic but looks good enough)
6357                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6358                         //r = brighten/(range*2+1);
6359                         r = brighten / (range * 2 + 1);
6360                         if(range >= 1)
6361                                 r *= (1 - x*x/(float)(range*range));
6362                         GL_Color(r, r, r, 1);
6363                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6364                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6365                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6366                         GL_BlendFunc(GL_ONE, GL_ONE);
6367                 }
6368
6369                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6370                 {
6371                         // copy the vertically or horizontally blurred bloom view to a texture
6372                         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);
6373                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6374                 }
6375         }
6376 }
6377
6378 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6379 {
6380         unsigned int permutation;
6381         float uservecs[4][4];
6382
6383         switch (vid.renderpath)
6384         {
6385         case RENDERPATH_GL20:
6386         case RENDERPATH_D3D9:
6387         case RENDERPATH_D3D10:
6388         case RENDERPATH_D3D11:
6389         case RENDERPATH_SOFT:
6390         case RENDERPATH_GLES2:
6391                 permutation =
6392                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6393                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6394                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6395                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6396                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6397
6398                 if (r_fb.colortexture)
6399                 {
6400                         if (!r_fb.fbo)
6401                         {
6402                                 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);
6403                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6404                         }
6405
6406                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6407                         {
6408                                 // declare variables
6409                                 float blur_factor, blur_mouseaccel, blur_velocity;
6410                                 static float blur_average; 
6411                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6412
6413                                 // set a goal for the factoring
6414                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6415                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6416                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6417                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6418                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6419                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6420
6421                                 // from the goal, pick an averaged value between goal and last value
6422                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6423                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6424
6425                                 // enforce minimum amount of blur 
6426                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6427
6428                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6429
6430                                 // calculate values into a standard alpha
6431                                 cl.motionbluralpha = 1 - exp(-
6432                                                 (
6433                                                  (r_motionblur.value * blur_factor / 80)
6434                                                  +
6435                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6436                                                 )
6437                                                 /
6438                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6439                                           );
6440
6441                                 // randomization for the blur value to combat persistent ghosting
6442                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6443                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6444
6445                                 // apply the blur
6446                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6447                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6448                                 {
6449                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6450                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6451                                         switch(vid.renderpath)
6452                                         {
6453                                         case RENDERPATH_GL11:
6454                                         case RENDERPATH_GL13:
6455                                         case RENDERPATH_GL20:
6456                                         case RENDERPATH_GLES1:
6457                                         case RENDERPATH_GLES2:
6458                                         case RENDERPATH_SOFT:
6459                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6460                                                 break;
6461                                         case RENDERPATH_D3D9:
6462                                         case RENDERPATH_D3D10:
6463                                         case RENDERPATH_D3D11:
6464                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6465                                                 break;
6466                                         }
6467                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6468                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6469                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6470                                 }
6471
6472                                 // updates old view angles for next pass
6473                                 VectorCopy(cl.viewangles, blur_oldangles);
6474
6475                                 // copy view into the ghost texture
6476                                 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);
6477                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6478                                 r_fb.ghosttexture_valid = true;
6479                         }
6480                 }
6481                 else
6482                 {
6483                         // no r_fb.colortexture means we're rendering to the real fb
6484                         // we may still have to do view tint...
6485                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6486                         {
6487                                 // apply a color tint to the whole view
6488                                 R_ResetViewRendering2D(0, NULL, NULL);
6489                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6490                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6491                                 R_SetupShader_Generic_NoTexture(false, true);
6492                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6493                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6494                         }
6495                         break; // no screen processing, no bloom, skip it
6496                 }
6497
6498                 if (r_fb.bloomtexture[0])
6499                 {
6500                         // make the bloom texture
6501                         R_Bloom_MakeTexture();
6502                 }
6503
6504 #if _MSC_VER >= 1400
6505 #define sscanf sscanf_s
6506 #endif
6507                 memset(uservecs, 0, sizeof(uservecs));
6508                 if (r_glsl_postprocess_uservec1_enable.integer)
6509                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6510                 if (r_glsl_postprocess_uservec2_enable.integer)
6511                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6512                 if (r_glsl_postprocess_uservec3_enable.integer)
6513                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6514                 if (r_glsl_postprocess_uservec4_enable.integer)
6515                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6516
6517                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6518                 GL_Color(1, 1, 1, 1);
6519                 GL_BlendFunc(GL_ONE, GL_ZERO);
6520
6521                 switch(vid.renderpath)
6522                 {
6523                 case RENDERPATH_GL20:
6524                 case RENDERPATH_GLES2:
6525                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6526                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6527                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6528                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6529                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6530                         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]);
6531                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6532                         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]);
6533                         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]);
6534                         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]);
6535                         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]);
6536                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6537                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6538                         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);
6539                         break;
6540                 case RENDERPATH_D3D9:
6541 #ifdef SUPPORTD3D
6542                         // 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...
6543                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6544                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6545                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6546                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6547                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6548                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6549                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6550                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6551                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6552                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6553                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6554                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6555                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6556                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6557 #endif
6558                         break;
6559                 case RENDERPATH_D3D10:
6560                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6561                         break;
6562                 case RENDERPATH_D3D11:
6563                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6564                         break;
6565                 case RENDERPATH_SOFT:
6566                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6567                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6568                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6569                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6570                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6571                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6572                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6573                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6574                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6575                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6576                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6577                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6578                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6579                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6580                         break;
6581                 default:
6582                         break;
6583                 }
6584                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6585                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6586                 break;
6587         case RENDERPATH_GL11:
6588         case RENDERPATH_GL13:
6589         case RENDERPATH_GLES1:
6590                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6591                 {
6592                         // apply a color tint to the whole view
6593                         R_ResetViewRendering2D(0, NULL, NULL);
6594                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6595                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6596                         R_SetupShader_Generic_NoTexture(false, true);
6597                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6598                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6599                 }
6600                 break;
6601         }
6602 }
6603
6604 matrix4x4_t r_waterscrollmatrix;
6605
6606 void R_UpdateFog(void)
6607 {
6608         // Nehahra fog
6609         if (gamemode == GAME_NEHAHRA)
6610         {
6611                 if (gl_fogenable.integer)
6612                 {
6613                         r_refdef.oldgl_fogenable = true;
6614                         r_refdef.fog_density = gl_fogdensity.value;
6615                         r_refdef.fog_red = gl_fogred.value;
6616                         r_refdef.fog_green = gl_foggreen.value;
6617                         r_refdef.fog_blue = gl_fogblue.value;
6618                         r_refdef.fog_alpha = 1;
6619                         r_refdef.fog_start = 0;
6620                         r_refdef.fog_end = gl_skyclip.value;
6621                         r_refdef.fog_height = 1<<30;
6622                         r_refdef.fog_fadedepth = 128;
6623                 }
6624                 else if (r_refdef.oldgl_fogenable)
6625                 {
6626                         r_refdef.oldgl_fogenable = false;
6627                         r_refdef.fog_density = 0;
6628                         r_refdef.fog_red = 0;
6629                         r_refdef.fog_green = 0;
6630                         r_refdef.fog_blue = 0;
6631                         r_refdef.fog_alpha = 0;
6632                         r_refdef.fog_start = 0;
6633                         r_refdef.fog_end = 0;
6634                         r_refdef.fog_height = 1<<30;
6635                         r_refdef.fog_fadedepth = 128;
6636                 }
6637         }
6638
6639         // fog parms
6640         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6641         r_refdef.fog_start = max(0, r_refdef.fog_start);
6642         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6643
6644         if (r_refdef.fog_density && r_drawfog.integer)
6645         {
6646                 r_refdef.fogenabled = true;
6647                 // this is the point where the fog reaches 0.9986 alpha, which we
6648                 // consider a good enough cutoff point for the texture
6649                 // (0.9986 * 256 == 255.6)
6650                 if (r_fog_exp2.integer)
6651                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6652                 else
6653                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6654                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6655                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6656                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6657                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6658                         R_BuildFogHeightTexture();
6659                 // fog color was already set
6660                 // update the fog texture
6661                 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)
6662                         R_BuildFogTexture();
6663                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6664                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6665         }
6666         else
6667                 r_refdef.fogenabled = false;
6668
6669         // fog color
6670         if (r_refdef.fog_density)
6671         {
6672                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6673                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6674                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6675
6676                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6677                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6678                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6679                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6680
6681                 {
6682                         vec3_t fogvec;
6683                         VectorCopy(r_refdef.fogcolor, fogvec);
6684                         //   color.rgb *= ContrastBoost * SceneBrightness;
6685                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6686                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6687                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6688                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6689                 }
6690         }
6691 }
6692
6693 void R_UpdateVariables(void)
6694 {
6695         R_Textures_Frame();
6696
6697         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6698
6699         r_refdef.farclip = r_farclip_base.value;
6700         if (r_refdef.scene.worldmodel)
6701                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6702         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6703
6704         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6705                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6706         r_refdef.polygonfactor = 0;
6707         r_refdef.polygonoffset = 0;
6708         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6709         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6710
6711         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6712         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6713         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6714         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6715         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6716         if (FAKELIGHT_ENABLED)
6717         {
6718                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6719         }
6720         else if (r_refdef.scene.worldmodel)
6721         {
6722                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6723         }
6724         if (r_showsurfaces.integer)
6725         {
6726                 r_refdef.scene.rtworld = false;
6727                 r_refdef.scene.rtworldshadows = false;
6728                 r_refdef.scene.rtdlight = false;
6729                 r_refdef.scene.rtdlightshadows = false;
6730                 r_refdef.lightmapintensity = 0;
6731         }
6732
6733         switch(vid.renderpath)
6734         {
6735         case RENDERPATH_GL20:
6736         case RENDERPATH_D3D9:
6737         case RENDERPATH_D3D10:
6738         case RENDERPATH_D3D11:
6739         case RENDERPATH_SOFT:
6740         case RENDERPATH_GLES2:
6741                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6742                 {
6743                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6744                         {
6745                                 // build GLSL gamma texture
6746 #define RAMPWIDTH 256
6747                                 unsigned short ramp[RAMPWIDTH * 3];
6748                                 unsigned char rampbgr[RAMPWIDTH][4];
6749                                 int i;
6750
6751                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6752
6753                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6754                                 for(i = 0; i < RAMPWIDTH; ++i)
6755                                 {
6756                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6757                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6758                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6759                                         rampbgr[i][3] = 0;
6760                                 }
6761                                 if (r_texture_gammaramps)
6762                                 {
6763                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6764                                 }
6765                                 else
6766                                 {
6767                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6768                                 }
6769                         }
6770                 }
6771                 else
6772                 {
6773                         // remove GLSL gamma texture
6774                 }
6775                 break;
6776         case RENDERPATH_GL11:
6777         case RENDERPATH_GL13:
6778         case RENDERPATH_GLES1:
6779                 break;
6780         }
6781 }
6782
6783 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6784 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6785 /*
6786 ================
6787 R_SelectScene
6788 ================
6789 */
6790 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6791         if( scenetype != r_currentscenetype ) {
6792                 // store the old scenetype
6793                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6794                 r_currentscenetype = scenetype;
6795                 // move in the new scene
6796                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6797         }
6798 }
6799
6800 /*
6801 ================
6802 R_GetScenePointer
6803 ================
6804 */
6805 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6806 {
6807         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6808         if( scenetype == r_currentscenetype ) {
6809                 return &r_refdef.scene;
6810         } else {
6811                 return &r_scenes_store[ scenetype ];
6812         }
6813 }
6814
6815 static int R_SortEntities_Compare(const void *ap, const void *bp)
6816 {
6817         const entity_render_t *a = *(const entity_render_t **)ap;
6818         const entity_render_t *b = *(const entity_render_t **)bp;
6819
6820         // 1. compare model
6821         if(a->model < b->model)
6822                 return -1;
6823         if(a->model > b->model)
6824                 return +1;
6825
6826         // 2. compare skin
6827         // TODO possibly calculate the REAL skinnum here first using
6828         // skinscenes?
6829         if(a->skinnum < b->skinnum)
6830                 return -1;
6831         if(a->skinnum > b->skinnum)
6832                 return +1;
6833
6834         // everything we compared is equal
6835         return 0;
6836 }
6837 static void R_SortEntities(void)
6838 {
6839         // below or equal 2 ents, sorting never gains anything
6840         if(r_refdef.scene.numentities <= 2)
6841                 return;
6842         // sort
6843         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6844 }
6845
6846 /*
6847 ================
6848 R_RenderView
6849 ================
6850 */
6851 int dpsoftrast_test;
6852 extern cvar_t r_shadow_bouncegrid;
6853 void R_RenderView(void)
6854 {
6855         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6856         int fbo;
6857         rtexture_t *depthtexture;
6858         rtexture_t *colortexture;
6859
6860         dpsoftrast_test = r_test.integer;
6861
6862         if (r_timereport_active)
6863                 R_TimeReport("start");
6864         r_textureframe++; // used only by R_GetCurrentTexture
6865         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6866
6867         if(R_CompileShader_CheckStaticParms())
6868                 R_GLSL_Restart_f();
6869
6870         if (!r_drawentities.integer)
6871                 r_refdef.scene.numentities = 0;
6872         else if (r_sortentities.integer)
6873                 R_SortEntities();
6874
6875         R_AnimCache_ClearCache();
6876         R_FrameData_NewFrame();
6877
6878         /* adjust for stereo display */
6879         if(R_Stereo_Active())
6880         {
6881                 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);
6882                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6883         }
6884
6885         if (r_refdef.view.isoverlay)
6886         {
6887                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6888                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6889                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6890                 R_TimeReport("depthclear");
6891
6892                 r_refdef.view.showdebug = false;
6893
6894                 r_fb.water.enabled = false;
6895                 r_fb.water.numwaterplanes = 0;
6896
6897                 R_RenderScene(0, NULL, NULL);
6898
6899                 r_refdef.view.matrix = originalmatrix;
6900
6901                 CHECKGLERROR
6902                 return;
6903         }
6904
6905         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6906         {
6907                 r_refdef.view.matrix = originalmatrix;
6908                 return;
6909         }
6910
6911         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6912
6913         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6914                 // in sRGB fallback, behave similar to true sRGB: convert this
6915                 // value from linear to sRGB
6916                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6917
6918         R_RenderView_UpdateViewVectors();
6919
6920         R_Shadow_UpdateWorldLightSelection();
6921
6922         R_Bloom_StartFrame();
6923
6924         // apply bloom brightness offset
6925         if(r_fb.bloomtexture[0])
6926                 r_refdef.view.colorscale *= r_bloom_scenebrightness.value;
6927
6928         R_Water_StartFrame();
6929
6930         // now we probably have an fbo to render into
6931         fbo = r_fb.fbo;
6932         depthtexture = r_fb.depthtexture;
6933         colortexture = r_fb.colortexture;
6934
6935         CHECKGLERROR
6936         if (r_timereport_active)
6937                 R_TimeReport("viewsetup");
6938
6939         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6940
6941         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6942         {
6943                 R_ClearScreen(r_refdef.fogenabled);
6944                 if (r_timereport_active)
6945                         R_TimeReport("viewclear");
6946         }
6947         r_refdef.view.clear = true;
6948
6949         r_refdef.view.showdebug = true;
6950
6951         R_View_Update();
6952         if (r_timereport_active)
6953                 R_TimeReport("visibility");
6954
6955         R_AnimCache_CacheVisibleEntities();
6956         if (r_timereport_active)
6957                 R_TimeReport("animcache");
6958
6959         R_Shadow_UpdateBounceGridTexture();
6960         if (r_timereport_active && r_shadow_bouncegrid.integer)
6961                 R_TimeReport("bouncegrid");
6962
6963         r_fb.water.numwaterplanes = 0;
6964         if (r_fb.water.enabled)
6965                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6966
6967         R_RenderScene(fbo, depthtexture, colortexture);
6968         r_fb.water.numwaterplanes = 0;
6969
6970         R_BlendView(fbo, depthtexture, colortexture);
6971         if (r_timereport_active)
6972                 R_TimeReport("blendview");
6973
6974         GL_Scissor(0, 0, vid.width, vid.height);
6975         GL_ScissorTest(false);
6976
6977         r_refdef.view.matrix = originalmatrix;
6978
6979         CHECKGLERROR
6980 }
6981
6982 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6983 {
6984         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6985         {
6986                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6987                 if (r_timereport_active)
6988                         R_TimeReport("waterworld");
6989         }
6990
6991         // don't let sound skip if going slow
6992         if (r_refdef.scene.extraupdate)
6993                 S_ExtraUpdate ();
6994
6995         R_DrawModelsAddWaterPlanes();
6996         if (r_timereport_active)
6997                 R_TimeReport("watermodels");
6998
6999         if (r_fb.water.numwaterplanes)
7000         {
7001                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
7002                 if (r_timereport_active)
7003                         R_TimeReport("waterscenes");
7004         }
7005 }
7006
7007 extern cvar_t cl_locs_show;
7008 static void R_DrawLocs(void);
7009 static void R_DrawEntityBBoxes(void);
7010 static void R_DrawModelDecals(void);
7011 extern cvar_t cl_decals_newsystem;
7012 extern qboolean r_shadow_usingdeferredprepass;
7013 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7014 {
7015         qboolean shadowmapping = false;
7016
7017         if (r_timereport_active)
7018                 R_TimeReport("beginscene");
7019
7020         r_refdef.stats.renders++;
7021
7022         R_UpdateFog();
7023
7024         // don't let sound skip if going slow
7025         if (r_refdef.scene.extraupdate)
7026                 S_ExtraUpdate ();
7027
7028         R_MeshQueue_BeginScene();
7029
7030         R_SkyStartFrame();
7031
7032         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);
7033
7034         if (r_timereport_active)
7035                 R_TimeReport("skystartframe");
7036
7037         if (cl.csqc_vidvars.drawworld)
7038         {
7039                 // don't let sound skip if going slow
7040                 if (r_refdef.scene.extraupdate)
7041                         S_ExtraUpdate ();
7042
7043                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7044                 {
7045                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7046                         if (r_timereport_active)
7047                                 R_TimeReport("worldsky");
7048                 }
7049
7050                 if (R_DrawBrushModelsSky() && r_timereport_active)
7051                         R_TimeReport("bmodelsky");
7052
7053                 if (skyrendermasked && skyrenderlater)
7054                 {
7055                         // we have to force off the water clipping plane while rendering sky
7056                         R_SetupView(false, fbo, depthtexture, colortexture);
7057                         R_Sky();
7058                         R_SetupView(true, fbo, depthtexture, colortexture);
7059                         if (r_timereport_active)
7060                                 R_TimeReport("sky");
7061                 }
7062         }
7063
7064         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7065         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7066                 R_Shadow_PrepareModelShadows();
7067         if (r_timereport_active)
7068                 R_TimeReport("preparelights");
7069
7070         if (R_Shadow_ShadowMappingEnabled())
7071                 shadowmapping = true;
7072
7073         if (r_shadow_usingdeferredprepass)
7074                 R_Shadow_DrawPrepass();
7075
7076         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7077         {
7078                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7079                 if (r_timereport_active)
7080                         R_TimeReport("worlddepth");
7081         }
7082         if (r_depthfirst.integer >= 2)
7083         {
7084                 R_DrawModelsDepth();
7085                 if (r_timereport_active)
7086                         R_TimeReport("modeldepth");
7087         }
7088
7089         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7090         {
7091                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7092                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7093                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7094                 // don't let sound skip if going slow
7095                 if (r_refdef.scene.extraupdate)
7096                         S_ExtraUpdate ();
7097         }
7098
7099         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7100         {
7101                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7102                 if (r_timereport_active)
7103                         R_TimeReport("world");
7104         }
7105
7106         // don't let sound skip if going slow
7107         if (r_refdef.scene.extraupdate)
7108                 S_ExtraUpdate ();
7109
7110         R_DrawModels();
7111         if (r_timereport_active)
7112                 R_TimeReport("models");
7113
7114         // don't let sound skip if going slow
7115         if (r_refdef.scene.extraupdate)
7116                 S_ExtraUpdate ();
7117
7118         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7119         {
7120                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7121                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7122                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7123                 // don't let sound skip if going slow
7124                 if (r_refdef.scene.extraupdate)
7125                         S_ExtraUpdate ();
7126         }
7127
7128         if (!r_shadow_usingdeferredprepass)
7129         {
7130                 R_Shadow_DrawLights();
7131                 if (r_timereport_active)
7132                         R_TimeReport("rtlights");
7133         }
7134
7135         // don't let sound skip if going slow
7136         if (r_refdef.scene.extraupdate)
7137                 S_ExtraUpdate ();
7138
7139         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7140         {
7141                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7142                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7143                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7144                 // don't let sound skip if going slow
7145                 if (r_refdef.scene.extraupdate)
7146                         S_ExtraUpdate ();
7147         }
7148
7149         if (cl.csqc_vidvars.drawworld)
7150         {
7151                 if (cl_decals_newsystem.integer)
7152                 {
7153                         R_DrawModelDecals();
7154                         if (r_timereport_active)
7155                                 R_TimeReport("modeldecals");
7156                 }
7157                 else
7158                 {
7159                         R_DrawDecals();
7160                         if (r_timereport_active)
7161                                 R_TimeReport("decals");
7162                 }
7163
7164                 R_DrawParticles();
7165                 if (r_timereport_active)
7166                         R_TimeReport("particles");
7167
7168                 R_DrawExplosions();
7169                 if (r_timereport_active)
7170                         R_TimeReport("explosions");
7171
7172                 R_DrawLightningBeams();
7173                 if (r_timereport_active)
7174                         R_TimeReport("lightning");
7175         }
7176
7177         if (cl.csqc_loaded)
7178                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7179
7180         if (r_refdef.view.showdebug)
7181         {
7182                 if (cl_locs_show.integer)
7183                 {
7184                         R_DrawLocs();
7185                         if (r_timereport_active)
7186                                 R_TimeReport("showlocs");
7187                 }
7188
7189                 if (r_drawportals.integer)
7190                 {
7191                         R_DrawPortals();
7192                         if (r_timereport_active)
7193                                 R_TimeReport("portals");
7194                 }
7195
7196                 if (r_showbboxes.value > 0)
7197                 {
7198                         R_DrawEntityBBoxes();
7199                         if (r_timereport_active)
7200                                 R_TimeReport("bboxes");
7201                 }
7202         }
7203
7204         if (r_transparent.integer)
7205         {
7206                 R_MeshQueue_RenderTransparent();
7207                 if (r_timereport_active)
7208                         R_TimeReport("drawtrans");
7209         }
7210
7211         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))
7212         {
7213                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7214                 if (r_timereport_active)
7215                         R_TimeReport("worlddebug");
7216                 R_DrawModelsDebug();
7217                 if (r_timereport_active)
7218                         R_TimeReport("modeldebug");
7219         }
7220
7221         if (cl.csqc_vidvars.drawworld)
7222         {
7223                 R_Shadow_DrawCoronas();
7224                 if (r_timereport_active)
7225                         R_TimeReport("coronas");
7226         }
7227
7228 #if 0
7229         {
7230                 GL_DepthTest(false);
7231                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7232                 GL_Color(1, 1, 1, 1);
7233                 qglBegin(GL_POLYGON);
7234                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7235                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7236                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7237                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7238                 qglEnd();
7239                 qglBegin(GL_POLYGON);
7240                 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]);
7241                 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]);
7242                 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]);
7243                 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]);
7244                 qglEnd();
7245                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7246         }
7247 #endif
7248
7249         // don't let sound skip if going slow
7250         if (r_refdef.scene.extraupdate)
7251                 S_ExtraUpdate ();
7252 }
7253
7254 static const unsigned short bboxelements[36] =
7255 {
7256         5, 1, 3, 5, 3, 7,
7257         6, 2, 0, 6, 0, 4,
7258         7, 3, 2, 7, 2, 6,
7259         4, 0, 1, 4, 1, 5,
7260         4, 5, 7, 4, 7, 6,
7261         1, 0, 2, 1, 2, 3,
7262 };
7263
7264 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7265 {
7266         int i;
7267         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7268
7269         RSurf_ActiveWorldEntity();
7270
7271         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7272         GL_DepthMask(false);
7273         GL_DepthRange(0, 1);
7274         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7275 //      R_Mesh_ResetTextureState();
7276
7277         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7278         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7279         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7280         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7281         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7282         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7283         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7284         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7285         R_FillColors(color4f, 8, cr, cg, cb, ca);
7286         if (r_refdef.fogenabled)
7287         {
7288                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7289                 {
7290                         f1 = RSurf_FogVertex(v);
7291                         f2 = 1 - f1;
7292                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7293                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7294                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7295                 }
7296         }
7297         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7298         R_Mesh_ResetTextureState();
7299         R_SetupShader_Generic_NoTexture(false, false);
7300         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7301 }
7302
7303 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7304 {
7305         prvm_prog_t *prog = SVVM_prog;
7306         int i;
7307         float color[4];
7308         prvm_edict_t *edict;
7309
7310         // this function draws bounding boxes of server entities
7311         if (!sv.active)
7312                 return;
7313
7314         GL_CullFace(GL_NONE);
7315         R_SetupShader_Generic_NoTexture(false, false);
7316
7317         for (i = 0;i < numsurfaces;i++)
7318         {
7319                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7320                 switch ((int)PRVM_serveredictfloat(edict, solid))
7321                 {
7322                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7323                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7324                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7325                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7326                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7327                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7328                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7329                 }
7330                 color[3] *= r_showbboxes.value;
7331                 color[3] = bound(0, color[3], 1);
7332                 GL_DepthTest(!r_showdisabledepthtest.integer);
7333                 GL_CullFace(r_refdef.view.cullface_front);
7334                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7335         }
7336 }
7337
7338 static void R_DrawEntityBBoxes(void)
7339 {
7340         int i;
7341         prvm_edict_t *edict;
7342         vec3_t center;
7343         prvm_prog_t *prog = SVVM_prog;
7344
7345         // this function draws bounding boxes of server entities
7346         if (!sv.active)
7347                 return;
7348
7349         for (i = 0;i < prog->num_edicts;i++)
7350         {
7351                 edict = PRVM_EDICT_NUM(i);
7352                 if (edict->priv.server->free)
7353                         continue;
7354                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7355                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7356                         continue;
7357                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7358                         continue;
7359                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7360                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7361         }
7362 }
7363
7364 static const int nomodelelement3i[24] =
7365 {
7366         5, 2, 0,
7367         5, 1, 2,
7368         5, 0, 3,
7369         5, 3, 1,
7370         0, 2, 4,
7371         2, 1, 4,
7372         3, 0, 4,
7373         1, 3, 4
7374 };
7375
7376 static const unsigned short nomodelelement3s[24] =
7377 {
7378         5, 2, 0,
7379         5, 1, 2,
7380         5, 0, 3,
7381         5, 3, 1,
7382         0, 2, 4,
7383         2, 1, 4,
7384         3, 0, 4,
7385         1, 3, 4
7386 };
7387
7388 static const float nomodelvertex3f[6*3] =
7389 {
7390         -16,   0,   0,
7391          16,   0,   0,
7392           0, -16,   0,
7393           0,  16,   0,
7394           0,   0, -16,
7395           0,   0,  16
7396 };
7397
7398 static const float nomodelcolor4f[6*4] =
7399 {
7400         0.0f, 0.0f, 0.5f, 1.0f,
7401         0.0f, 0.0f, 0.5f, 1.0f,
7402         0.0f, 0.5f, 0.0f, 1.0f,
7403         0.0f, 0.5f, 0.0f, 1.0f,
7404         0.5f, 0.0f, 0.0f, 1.0f,
7405         0.5f, 0.0f, 0.0f, 1.0f
7406 };
7407
7408 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7409 {
7410         int i;
7411         float f1, f2, *c;
7412         float color4f[6*4];
7413
7414         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);
7415
7416         // this is only called once per entity so numsurfaces is always 1, and
7417         // surfacelist is always {0}, so this code does not handle batches
7418
7419         if (rsurface.ent_flags & RENDER_ADDITIVE)
7420         {
7421                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7422                 GL_DepthMask(false);
7423         }
7424         else if (rsurface.colormod[3] < 1)
7425         {
7426                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7427                 GL_DepthMask(false);
7428         }
7429         else
7430         {
7431                 GL_BlendFunc(GL_ONE, GL_ZERO);
7432                 GL_DepthMask(true);
7433         }
7434         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7435         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7436         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7437         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7438         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7439         for (i = 0, c = color4f;i < 6;i++, c += 4)
7440         {
7441                 c[0] *= rsurface.colormod[0];
7442                 c[1] *= rsurface.colormod[1];
7443                 c[2] *= rsurface.colormod[2];
7444                 c[3] *= rsurface.colormod[3];
7445         }
7446         if (r_refdef.fogenabled)
7447         {
7448                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7449                 {
7450                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7451                         f2 = 1 - f1;
7452                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7453                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7454                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7455                 }
7456         }
7457 //      R_Mesh_ResetTextureState();
7458         R_SetupShader_Generic_NoTexture(false, false);
7459         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7460         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7461 }
7462
7463 void R_DrawNoModel(entity_render_t *ent)
7464 {
7465         vec3_t org;
7466         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7467         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7468                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? TRANSPARENTSORT_HUD : TRANSPARENTSORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7469         else
7470                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7471 }
7472
7473 void R_CalcBeam_Vertex3f (float *vert, const float *org1, const float *org2, float width)
7474 {
7475         vec3_t right1, right2, diff, normal;
7476
7477         VectorSubtract (org2, org1, normal);
7478
7479         // calculate 'right' vector for start
7480         VectorSubtract (r_refdef.view.origin, org1, diff);
7481         CrossProduct (normal, diff, right1);
7482         VectorNormalize (right1);
7483
7484         // calculate 'right' vector for end
7485         VectorSubtract (r_refdef.view.origin, org2, diff);
7486         CrossProduct (normal, diff, right2);
7487         VectorNormalize (right2);
7488
7489         vert[ 0] = org1[0] + width * right1[0];
7490         vert[ 1] = org1[1] + width * right1[1];
7491         vert[ 2] = org1[2] + width * right1[2];
7492         vert[ 3] = org1[0] - width * right1[0];
7493         vert[ 4] = org1[1] - width * right1[1];
7494         vert[ 5] = org1[2] - width * right1[2];
7495         vert[ 6] = org2[0] - width * right2[0];
7496         vert[ 7] = org2[1] - width * right2[1];
7497         vert[ 8] = org2[2] - width * right2[2];
7498         vert[ 9] = org2[0] + width * right2[0];
7499         vert[10] = org2[1] + width * right2[1];
7500         vert[11] = org2[2] + width * right2[2];
7501 }
7502
7503 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)
7504 {
7505         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7506         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7507         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7508         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7509         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7510         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7511         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7512         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7513         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7514         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7515         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7516         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7517 }
7518
7519 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7520 {
7521         int i;
7522         float *vertex3f;
7523         float v[3];
7524         VectorSet(v, x, y, z);
7525         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7526                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7527                         break;
7528         if (i == mesh->numvertices)
7529         {
7530                 if (mesh->numvertices < mesh->maxvertices)
7531                 {
7532                         VectorCopy(v, vertex3f);
7533                         mesh->numvertices++;
7534                 }
7535                 return mesh->numvertices;
7536         }
7537         else
7538                 return i;
7539 }
7540
7541 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7542 {
7543         int i;
7544         int *e, element[3];
7545         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7546         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7547         e = mesh->element3i + mesh->numtriangles * 3;
7548         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7549         {
7550                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7551                 if (mesh->numtriangles < mesh->maxtriangles)
7552                 {
7553                         *e++ = element[0];
7554                         *e++ = element[1];
7555                         *e++ = element[2];
7556                         mesh->numtriangles++;
7557                 }
7558                 element[1] = element[2];
7559         }
7560 }
7561
7562 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7563 {
7564         int i;
7565         int *e, element[3];
7566         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7567         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7568         e = mesh->element3i + mesh->numtriangles * 3;
7569         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7570         {
7571                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7572                 if (mesh->numtriangles < mesh->maxtriangles)
7573                 {
7574                         *e++ = element[0];
7575                         *e++ = element[1];
7576                         *e++ = element[2];
7577                         mesh->numtriangles++;
7578                 }
7579                 element[1] = element[2];
7580         }
7581 }
7582
7583 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7584 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7585 {
7586         int planenum, planenum2;
7587         int w;
7588         int tempnumpoints;
7589         mplane_t *plane, *plane2;
7590         double maxdist;
7591         double temppoints[2][256*3];
7592         // figure out how large a bounding box we need to properly compute this brush
7593         maxdist = 0;
7594         for (w = 0;w < numplanes;w++)
7595                 maxdist = max(maxdist, fabs(planes[w].dist));
7596         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7597         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7598         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7599         {
7600                 w = 0;
7601                 tempnumpoints = 4;
7602                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7603                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7604                 {
7605                         if (planenum2 == planenum)
7606                                 continue;
7607                         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);
7608                         w = !w;
7609                 }
7610                 if (tempnumpoints < 3)
7611                         continue;
7612                 // generate elements forming a triangle fan for this polygon
7613                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7614         }
7615 }
7616
7617 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)
7618 {
7619         texturelayer_t *layer;
7620         layer = t->currentlayers + t->currentnumlayers++;
7621         layer->type = type;
7622         layer->depthmask = depthmask;
7623         layer->blendfunc1 = blendfunc1;
7624         layer->blendfunc2 = blendfunc2;
7625         layer->texture = texture;
7626         layer->texmatrix = *matrix;
7627         layer->color[0] = r;
7628         layer->color[1] = g;
7629         layer->color[2] = b;
7630         layer->color[3] = a;
7631 }
7632
7633 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7634 {
7635         if(parms[0] == 0 && parms[1] == 0)
7636                 return false;
7637         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7638                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7639                         return false;
7640         return true;
7641 }
7642
7643 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7644 {
7645         double index, f;
7646         index = parms[2] + rsurface.shadertime * parms[3];
7647         index -= floor(index);
7648         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7649         {
7650         default:
7651         case Q3WAVEFUNC_NONE:
7652         case Q3WAVEFUNC_NOISE:
7653         case Q3WAVEFUNC_COUNT:
7654                 f = 0;
7655                 break;
7656         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7657         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7658         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7659         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7660         case Q3WAVEFUNC_TRIANGLE:
7661                 index *= 4;
7662                 f = index - floor(index);
7663                 if (index < 1)
7664                 {
7665                         // f = f;
7666                 }
7667                 else if (index < 2)
7668                         f = 1 - f;
7669                 else if (index < 3)
7670                         f = -f;
7671                 else
7672                         f = -(1 - f);
7673                 break;
7674         }
7675         f = parms[0] + parms[1] * f;
7676         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7677                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7678         return (float) f;
7679 }
7680
7681 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7682 {
7683         int w, h, idx;
7684         double f;
7685         double offsetd[2];
7686         float tcmat[12];
7687         matrix4x4_t matrix, temp;
7688         switch(tcmod->tcmod)
7689         {
7690                 case Q3TCMOD_COUNT:
7691                 case Q3TCMOD_NONE:
7692                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7693                                 matrix = r_waterscrollmatrix;
7694                         else
7695                                 matrix = identitymatrix;
7696                         break;
7697                 case Q3TCMOD_ENTITYTRANSLATE:
7698                         // this is used in Q3 to allow the gamecode to control texcoord
7699                         // scrolling on the entity, which is not supported in darkplaces yet.
7700                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7701                         break;
7702                 case Q3TCMOD_ROTATE:
7703                         f = tcmod->parms[0] * rsurface.shadertime;
7704                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7705                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7706                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7707                         break;
7708                 case Q3TCMOD_SCALE:
7709                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7710                         break;
7711                 case Q3TCMOD_SCROLL:
7712                         // extra care is needed because of precision breakdown with large values of time
7713                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7714                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7715                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7716                         break;
7717                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7718                         w = (int) tcmod->parms[0];
7719                         h = (int) tcmod->parms[1];
7720                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7721                         f = f - floor(f);
7722                         idx = (int) floor(f * w * h);
7723                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7724                         break;
7725                 case Q3TCMOD_STRETCH:
7726                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7727                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7728                         break;
7729                 case Q3TCMOD_TRANSFORM:
7730                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7731                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7732                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7733                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7734                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7735                         break;
7736                 case Q3TCMOD_TURBULENT:
7737                         // this is handled in the RSurf_PrepareVertices function
7738                         matrix = identitymatrix;
7739                         break;
7740         }
7741         temp = *texmatrix;
7742         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7743 }
7744
7745 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7746 {
7747         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7748         char name[MAX_QPATH];
7749         skinframe_t *skinframe;
7750         unsigned char pixels[296*194];
7751         strlcpy(cache->name, skinname, sizeof(cache->name));
7752         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7753         if (developer_loading.integer)
7754                 Con_Printf("loading %s\n", name);
7755         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7756         if (!skinframe || !skinframe->base)
7757         {
7758                 unsigned char *f;
7759                 fs_offset_t filesize;
7760                 skinframe = NULL;
7761                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7762                 if (f)
7763                 {
7764                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7765                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7766                         Mem_Free(f);
7767                 }
7768         }
7769         cache->skinframe = skinframe;
7770 }
7771
7772 texture_t *R_GetCurrentTexture(texture_t *t)
7773 {
7774         int i;
7775         const entity_render_t *ent = rsurface.entity;
7776         dp_model_t *model = ent->model; // when calling this, ent must not be NULL
7777         q3shaderinfo_layer_tcmod_t *tcmod;
7778
7779         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7780                 return t->currentframe;
7781         t->update_lastrenderframe = r_textureframe;
7782         t->update_lastrenderentity = (void *)ent;
7783
7784         if(ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7785                 t->camera_entity = ent->entitynumber;
7786         else
7787                 t->camera_entity = 0;
7788
7789         // switch to an alternate material if this is a q1bsp animated material
7790         {
7791                 texture_t *texture = t;
7792                 int s = rsurface.ent_skinnum;
7793                 if ((unsigned int)s >= (unsigned int)model->numskins)
7794                         s = 0;
7795                 if (model->skinscenes)
7796                 {
7797                         if (model->skinscenes[s].framecount > 1)
7798                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7799                         else
7800                                 s = model->skinscenes[s].firstframe;
7801                 }
7802                 if (s > 0)
7803                         t = t + s * model->num_surfaces;
7804                 if (t->animated)
7805                 {
7806                         // use an alternate animation if the entity's frame is not 0,
7807                         // and only if the texture has an alternate animation
7808                         if (rsurface.ent_alttextures && t->anim_total[1])
7809                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7810                         else
7811                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7812                 }
7813                 texture->currentframe = t;
7814         }
7815
7816         // update currentskinframe to be a qw skin or animation frame
7817         if (rsurface.ent_qwskin >= 0)
7818         {
7819                 i = rsurface.ent_qwskin;
7820                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7821                 {
7822                         r_qwskincache_size = cl.maxclients;
7823                         if (r_qwskincache)
7824                                 Mem_Free(r_qwskincache);
7825                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7826                 }
7827                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7828                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7829                 t->currentskinframe = r_qwskincache[i].skinframe;
7830                 if (t->currentskinframe == NULL)
7831                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7832         }
7833         else if (t->numskinframes >= 2)
7834                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7835         if (t->backgroundnumskinframes >= 2)
7836                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7837
7838         t->currentmaterialflags = t->basematerialflags;
7839         t->currentalpha = rsurface.colormod[3];
7840         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7841                 t->currentalpha *= r_wateralpha.value;
7842         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7843                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7844         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7845                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7846         if (!(rsurface.ent_flags & RENDER_LIGHT))
7847                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7848         else if (FAKELIGHT_ENABLED)
7849         {
7850                 // no modellight if using fakelight for the map
7851         }
7852         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7853         {
7854                 // pick a model lighting mode
7855                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7856                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7857                 else
7858                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7859         }
7860         if (rsurface.ent_flags & RENDER_ADDITIVE)
7861                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7862         else if (t->currentalpha < 1)
7863                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7864         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7865         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7866                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7867         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7868                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7869         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7870                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7871         if (t->backgroundnumskinframes)
7872                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7873         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7874         {
7875                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7876                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7877         }
7878         else
7879                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7880         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7881         {
7882                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7883                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7884         }
7885         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7886                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7887
7888         // there is no tcmod
7889         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7890         {
7891                 t->currenttexmatrix = r_waterscrollmatrix;
7892                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7893         }
7894         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7895         {
7896                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7897                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7898         }
7899
7900         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7901                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7902         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7903                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7904
7905         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7906         if (t->currentskinframe->qpixels)
7907                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7908         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7909         if (!t->basetexture)
7910                 t->basetexture = r_texture_notexture;
7911         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7912         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7913         t->nmaptexture = t->currentskinframe->nmap;
7914         if (!t->nmaptexture)
7915                 t->nmaptexture = r_texture_blanknormalmap;
7916         t->glosstexture = r_texture_black;
7917         t->glowtexture = t->currentskinframe->glow;
7918         t->fogtexture = t->currentskinframe->fog;
7919         t->reflectmasktexture = t->currentskinframe->reflect;
7920         if (t->backgroundnumskinframes)
7921         {
7922                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7923                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7924                 t->backgroundglosstexture = r_texture_black;
7925                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7926                 if (!t->backgroundnmaptexture)
7927                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7928                 // make sure that if glow is going to be used, both textures are not NULL
7929                 if (!t->backgroundglowtexture && t->glowtexture)
7930                         t->backgroundglowtexture = r_texture_black;
7931                 if (!t->glowtexture && t->backgroundglowtexture)
7932                         t->glowtexture = r_texture_black;
7933         }
7934         else
7935         {
7936                 t->backgroundbasetexture = r_texture_white;
7937                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7938                 t->backgroundglosstexture = r_texture_black;
7939                 t->backgroundglowtexture = NULL;
7940         }
7941         t->specularpower = r_shadow_glossexponent.value;
7942         // TODO: store reference values for these in the texture?
7943         t->specularscale = 0;
7944         if (r_shadow_gloss.integer > 0)
7945         {
7946                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7947                 {
7948                         if (r_shadow_glossintensity.value > 0)
7949                         {
7950                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7951                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7952                                 t->specularscale = r_shadow_glossintensity.value;
7953                         }
7954                 }
7955                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7956                 {
7957                         t->glosstexture = r_texture_white;
7958                         t->backgroundglosstexture = r_texture_white;
7959                         t->specularscale = r_shadow_gloss2intensity.value;
7960                         t->specularpower = r_shadow_gloss2exponent.value;
7961                 }
7962         }
7963         t->specularscale *= t->specularscalemod;
7964         t->specularpower *= t->specularpowermod;
7965         t->rtlightambient = 0;
7966
7967         // lightmaps mode looks bad with dlights using actual texturing, so turn
7968         // off the colormap and glossmap, but leave the normalmap on as it still
7969         // accurately represents the shading involved
7970         if (gl_lightmaps.integer)
7971         {
7972                 t->basetexture = r_texture_grey128;
7973                 t->pantstexture = r_texture_black;
7974                 t->shirttexture = r_texture_black;
7975                 t->nmaptexture = r_texture_blanknormalmap;
7976                 t->glosstexture = r_texture_black;
7977                 t->glowtexture = NULL;
7978                 t->fogtexture = NULL;
7979                 t->reflectmasktexture = NULL;
7980                 t->backgroundbasetexture = NULL;
7981                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7982                 t->backgroundglosstexture = r_texture_black;
7983                 t->backgroundglowtexture = NULL;
7984                 t->specularscale = 0;
7985                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7986         }
7987
7988         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7989         VectorClear(t->dlightcolor);
7990         t->currentnumlayers = 0;
7991         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7992         {
7993                 int blendfunc1, blendfunc2;
7994                 qboolean depthmask;
7995                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7996                 {
7997                         blendfunc1 = GL_SRC_ALPHA;
7998                         blendfunc2 = GL_ONE;
7999                 }
8000                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
8001                 {
8002                         blendfunc1 = GL_SRC_ALPHA;
8003                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
8004                 }
8005                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
8006                 {
8007                         blendfunc1 = t->customblendfunc[0];
8008                         blendfunc2 = t->customblendfunc[1];
8009                 }
8010                 else
8011                 {
8012                         blendfunc1 = GL_ONE;
8013                         blendfunc2 = GL_ZERO;
8014                 }
8015                 // don't colormod evilblend textures
8016                 if(!(R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD))
8017                         VectorSet(t->lightmapcolor, 1, 1, 1);
8018                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8019                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8020                 {
8021                         // fullbright is not affected by r_refdef.lightmapintensity
8022                         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]);
8023                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8024                                 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]);
8025                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8026                                 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]);
8027                 }
8028                 else
8029                 {
8030                         vec3_t ambientcolor;
8031                         float colorscale;
8032                         // set the color tint used for lights affecting this surface
8033                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8034                         colorscale = 2;
8035                         // q3bsp has no lightmap updates, so the lightstylevalue that
8036                         // would normally be baked into the lightmap must be
8037                         // applied to the color
8038                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8039                         if (model->type == mod_brushq3)
8040                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8041                         colorscale *= r_refdef.lightmapintensity;
8042                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8043                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8044                         // basic lit geometry
8045                         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]);
8046                         // add pants/shirt if needed
8047                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8048                                 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]);
8049                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8050                                 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]);
8051                         // now add ambient passes if needed
8052                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8053                         {
8054                                 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]);
8055                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8056                                         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]);
8057                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8058                                         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]);
8059                         }
8060                 }
8061                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8062                         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]);
8063                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8064                 {
8065                         // if this is opaque use alpha blend which will darken the earlier
8066                         // passes cheaply.
8067                         //
8068                         // if this is an alpha blended material, all the earlier passes
8069                         // were darkened by fog already, so we only need to add the fog
8070                         // color ontop through the fog mask texture
8071                         //
8072                         // if this is an additive blended material, all the earlier passes
8073                         // were darkened by fog already, and we should not add fog color
8074                         // (because the background was not darkened, there is no fog color
8075                         // that was lost behind it).
8076                         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]);
8077                 }
8078         }
8079
8080         return t->currentframe;
8081 }
8082
8083 rsurfacestate_t rsurface;
8084
8085 void RSurf_ActiveWorldEntity(void)
8086 {
8087         dp_model_t *model = r_refdef.scene.worldmodel;
8088         //if (rsurface.entity == r_refdef.scene.worldentity)
8089         //      return;
8090         rsurface.entity = r_refdef.scene.worldentity;
8091         rsurface.skeleton = NULL;
8092         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8093         rsurface.ent_skinnum = 0;
8094         rsurface.ent_qwskin = -1;
8095         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8096         rsurface.shadertime = r_refdef.scene.time;
8097         rsurface.matrix = identitymatrix;
8098         rsurface.inversematrix = identitymatrix;
8099         rsurface.matrixscale = 1;
8100         rsurface.inversematrixscale = 1;
8101         R_EntityMatrix(&identitymatrix);
8102         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8103         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8104         rsurface.fograngerecip = r_refdef.fograngerecip;
8105         rsurface.fogheightfade = r_refdef.fogheightfade;
8106         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8107         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8108         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8109         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8110         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8111         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8112         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8113         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8114         rsurface.colormod[3] = 1;
8115         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);
8116         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8117         rsurface.frameblend[0].lerp = 1;
8118         rsurface.ent_alttextures = false;
8119         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8120         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8121         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8122         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8123         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8124         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8125         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8126         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8127         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8128         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8129         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8130         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8131         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8132         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8133         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8134         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8135         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8136         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8137         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8138         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8139         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8140         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8141         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8142         rsurface.modelelement3i = model->surfmesh.data_element3i;
8143         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8144         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8145         rsurface.modelelement3s = model->surfmesh.data_element3s;
8146         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8147         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8148         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8149         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8150         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8151         rsurface.modelsurfaces = model->data_surfaces;
8152         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8153         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8154         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8155         rsurface.modelgeneratedvertex = false;
8156         rsurface.batchgeneratedvertex = false;
8157         rsurface.batchfirstvertex = 0;
8158         rsurface.batchnumvertices = 0;
8159         rsurface.batchfirsttriangle = 0;
8160         rsurface.batchnumtriangles = 0;
8161         rsurface.batchvertex3f  = NULL;
8162         rsurface.batchvertex3f_vertexbuffer = NULL;
8163         rsurface.batchvertex3f_bufferoffset = 0;
8164         rsurface.batchsvector3f = NULL;
8165         rsurface.batchsvector3f_vertexbuffer = NULL;
8166         rsurface.batchsvector3f_bufferoffset = 0;
8167         rsurface.batchtvector3f = NULL;
8168         rsurface.batchtvector3f_vertexbuffer = NULL;
8169         rsurface.batchtvector3f_bufferoffset = 0;
8170         rsurface.batchnormal3f  = NULL;
8171         rsurface.batchnormal3f_vertexbuffer = NULL;
8172         rsurface.batchnormal3f_bufferoffset = 0;
8173         rsurface.batchlightmapcolor4f = NULL;
8174         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8175         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8176         rsurface.batchtexcoordtexture2f = NULL;
8177         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8178         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8179         rsurface.batchtexcoordlightmap2f = NULL;
8180         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8181         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8182         rsurface.batchvertexmesh = NULL;
8183         rsurface.batchvertexmeshbuffer = NULL;
8184         rsurface.batchvertex3fbuffer = NULL;
8185         rsurface.batchelement3i = NULL;
8186         rsurface.batchelement3i_indexbuffer = NULL;
8187         rsurface.batchelement3i_bufferoffset = 0;
8188         rsurface.batchelement3s = NULL;
8189         rsurface.batchelement3s_indexbuffer = NULL;
8190         rsurface.batchelement3s_bufferoffset = 0;
8191         rsurface.passcolor4f = NULL;
8192         rsurface.passcolor4f_vertexbuffer = NULL;
8193         rsurface.passcolor4f_bufferoffset = 0;
8194         rsurface.forcecurrenttextureupdate = false;
8195 }
8196
8197 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8198 {
8199         dp_model_t *model = ent->model;
8200         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8201         //      return;
8202         rsurface.entity = (entity_render_t *)ent;
8203         rsurface.skeleton = ent->skeleton;
8204         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8205         rsurface.ent_skinnum = ent->skinnum;
8206         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;
8207         rsurface.ent_flags = ent->flags;
8208         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8209         rsurface.matrix = ent->matrix;
8210         rsurface.inversematrix = ent->inversematrix;
8211         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8212         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8213         R_EntityMatrix(&rsurface.matrix);
8214         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8215         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8216         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8217         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8218         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8219         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8220         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8221         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8222         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8223         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8224         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8225         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8226         rsurface.colormod[3] = ent->alpha;
8227         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8228         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8229         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8230         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8231         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8232         if (ent->model->brush.submodel && !prepass)
8233         {
8234                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8235                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8236         }
8237         if (model->surfmesh.isanimated && model->AnimateVertices)
8238         {
8239                 if (ent->animcache_vertex3f)
8240                 {
8241                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8242                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8243                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8244                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8245                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8246                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8247                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8248                 }
8249                 else if (wanttangents)
8250                 {
8251                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8252                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8253                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8254                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8255                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8256                         rsurface.modelvertexmesh = NULL;
8257                         rsurface.modelvertexmeshbuffer = NULL;
8258                         rsurface.modelvertex3fbuffer = NULL;
8259                 }
8260                 else if (wantnormals)
8261                 {
8262                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8263                         rsurface.modelsvector3f = NULL;
8264                         rsurface.modeltvector3f = NULL;
8265                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8266                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8267                         rsurface.modelvertexmesh = NULL;
8268                         rsurface.modelvertexmeshbuffer = NULL;
8269                         rsurface.modelvertex3fbuffer = NULL;
8270                 }
8271                 else
8272                 {
8273                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8274                         rsurface.modelsvector3f = NULL;
8275                         rsurface.modeltvector3f = NULL;
8276                         rsurface.modelnormal3f = NULL;
8277                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8278                         rsurface.modelvertexmesh = NULL;
8279                         rsurface.modelvertexmeshbuffer = NULL;
8280                         rsurface.modelvertex3fbuffer = NULL;
8281                 }
8282                 rsurface.modelvertex3f_vertexbuffer = 0;
8283                 rsurface.modelvertex3f_bufferoffset = 0;
8284                 rsurface.modelsvector3f_vertexbuffer = 0;
8285                 rsurface.modelsvector3f_bufferoffset = 0;
8286                 rsurface.modeltvector3f_vertexbuffer = 0;
8287                 rsurface.modeltvector3f_bufferoffset = 0;
8288                 rsurface.modelnormal3f_vertexbuffer = 0;
8289                 rsurface.modelnormal3f_bufferoffset = 0;
8290                 rsurface.modelgeneratedvertex = true;
8291         }
8292         else
8293         {
8294                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8295                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8296                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8297                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8298                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8299                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8300                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8301                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8302                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8303                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8304                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8305                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8306                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8307                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8308                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8309                 rsurface.modelgeneratedvertex = false;
8310         }
8311         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8312         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8313         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8314         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8315         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8316         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8317         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8318         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8319         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8320         rsurface.modelelement3i = model->surfmesh.data_element3i;
8321         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8322         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8323         rsurface.modelelement3s = model->surfmesh.data_element3s;
8324         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8325         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8326         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8327         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8328         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8329         rsurface.modelsurfaces = model->data_surfaces;
8330         rsurface.batchgeneratedvertex = false;
8331         rsurface.batchfirstvertex = 0;
8332         rsurface.batchnumvertices = 0;
8333         rsurface.batchfirsttriangle = 0;
8334         rsurface.batchnumtriangles = 0;
8335         rsurface.batchvertex3f  = NULL;
8336         rsurface.batchvertex3f_vertexbuffer = NULL;
8337         rsurface.batchvertex3f_bufferoffset = 0;
8338         rsurface.batchsvector3f = NULL;
8339         rsurface.batchsvector3f_vertexbuffer = NULL;
8340         rsurface.batchsvector3f_bufferoffset = 0;
8341         rsurface.batchtvector3f = NULL;
8342         rsurface.batchtvector3f_vertexbuffer = NULL;
8343         rsurface.batchtvector3f_bufferoffset = 0;
8344         rsurface.batchnormal3f  = NULL;
8345         rsurface.batchnormal3f_vertexbuffer = NULL;
8346         rsurface.batchnormal3f_bufferoffset = 0;
8347         rsurface.batchlightmapcolor4f = NULL;
8348         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8349         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8350         rsurface.batchtexcoordtexture2f = NULL;
8351         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8352         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8353         rsurface.batchtexcoordlightmap2f = NULL;
8354         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8355         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8356         rsurface.batchvertexmesh = NULL;
8357         rsurface.batchvertexmeshbuffer = NULL;
8358         rsurface.batchvertex3fbuffer = NULL;
8359         rsurface.batchelement3i = NULL;
8360         rsurface.batchelement3i_indexbuffer = NULL;
8361         rsurface.batchelement3i_bufferoffset = 0;
8362         rsurface.batchelement3s = NULL;
8363         rsurface.batchelement3s_indexbuffer = NULL;
8364         rsurface.batchelement3s_bufferoffset = 0;
8365         rsurface.passcolor4f = NULL;
8366         rsurface.passcolor4f_vertexbuffer = NULL;
8367         rsurface.passcolor4f_bufferoffset = 0;
8368         rsurface.forcecurrenttextureupdate = false;
8369 }
8370
8371 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)
8372 {
8373         rsurface.entity = r_refdef.scene.worldentity;
8374         rsurface.skeleton = NULL;
8375         rsurface.ent_skinnum = 0;
8376         rsurface.ent_qwskin = -1;
8377         rsurface.ent_flags = entflags;
8378         rsurface.shadertime = r_refdef.scene.time - shadertime;
8379         rsurface.modelnumvertices = numvertices;
8380         rsurface.modelnumtriangles = numtriangles;
8381         rsurface.matrix = *matrix;
8382         rsurface.inversematrix = *inversematrix;
8383         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8384         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8385         R_EntityMatrix(&rsurface.matrix);
8386         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8387         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8388         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8389         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8390         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8391         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8392         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8393         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8394         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8395         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8396         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8397         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8398         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);
8399         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8400         rsurface.frameblend[0].lerp = 1;
8401         rsurface.ent_alttextures = false;
8402         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8403         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8404         if (wanttangents)
8405         {
8406                 rsurface.modelvertex3f = (float *)vertex3f;
8407                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8408                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8409                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8410         }
8411         else if (wantnormals)
8412         {
8413                 rsurface.modelvertex3f = (float *)vertex3f;
8414                 rsurface.modelsvector3f = NULL;
8415                 rsurface.modeltvector3f = NULL;
8416                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8417         }
8418         else
8419         {
8420                 rsurface.modelvertex3f = (float *)vertex3f;
8421                 rsurface.modelsvector3f = NULL;
8422                 rsurface.modeltvector3f = NULL;
8423                 rsurface.modelnormal3f = NULL;
8424         }
8425         rsurface.modelvertexmesh = NULL;
8426         rsurface.modelvertexmeshbuffer = NULL;
8427         rsurface.modelvertex3fbuffer = NULL;
8428         rsurface.modelvertex3f_vertexbuffer = 0;
8429         rsurface.modelvertex3f_bufferoffset = 0;
8430         rsurface.modelsvector3f_vertexbuffer = 0;
8431         rsurface.modelsvector3f_bufferoffset = 0;
8432         rsurface.modeltvector3f_vertexbuffer = 0;
8433         rsurface.modeltvector3f_bufferoffset = 0;
8434         rsurface.modelnormal3f_vertexbuffer = 0;
8435         rsurface.modelnormal3f_bufferoffset = 0;
8436         rsurface.modelgeneratedvertex = true;
8437         rsurface.modellightmapcolor4f  = (float *)color4f;
8438         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8439         rsurface.modellightmapcolor4f_bufferoffset = 0;
8440         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8441         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8442         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8443         rsurface.modeltexcoordlightmap2f  = NULL;
8444         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8445         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8446         rsurface.modelelement3i = (int *)element3i;
8447         rsurface.modelelement3i_indexbuffer = NULL;
8448         rsurface.modelelement3i_bufferoffset = 0;
8449         rsurface.modelelement3s = (unsigned short *)element3s;
8450         rsurface.modelelement3s_indexbuffer = NULL;
8451         rsurface.modelelement3s_bufferoffset = 0;
8452         rsurface.modellightmapoffsets = NULL;
8453         rsurface.modelsurfaces = NULL;
8454         rsurface.batchgeneratedvertex = false;
8455         rsurface.batchfirstvertex = 0;
8456         rsurface.batchnumvertices = 0;
8457         rsurface.batchfirsttriangle = 0;
8458         rsurface.batchnumtriangles = 0;
8459         rsurface.batchvertex3f  = NULL;
8460         rsurface.batchvertex3f_vertexbuffer = NULL;
8461         rsurface.batchvertex3f_bufferoffset = 0;
8462         rsurface.batchsvector3f = NULL;
8463         rsurface.batchsvector3f_vertexbuffer = NULL;
8464         rsurface.batchsvector3f_bufferoffset = 0;
8465         rsurface.batchtvector3f = NULL;
8466         rsurface.batchtvector3f_vertexbuffer = NULL;
8467         rsurface.batchtvector3f_bufferoffset = 0;
8468         rsurface.batchnormal3f  = NULL;
8469         rsurface.batchnormal3f_vertexbuffer = NULL;
8470         rsurface.batchnormal3f_bufferoffset = 0;
8471         rsurface.batchlightmapcolor4f = NULL;
8472         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8473         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8474         rsurface.batchtexcoordtexture2f = NULL;
8475         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8476         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8477         rsurface.batchtexcoordlightmap2f = NULL;
8478         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8479         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8480         rsurface.batchvertexmesh = NULL;
8481         rsurface.batchvertexmeshbuffer = NULL;
8482         rsurface.batchvertex3fbuffer = NULL;
8483         rsurface.batchelement3i = NULL;
8484         rsurface.batchelement3i_indexbuffer = NULL;
8485         rsurface.batchelement3i_bufferoffset = 0;
8486         rsurface.batchelement3s = NULL;
8487         rsurface.batchelement3s_indexbuffer = NULL;
8488         rsurface.batchelement3s_bufferoffset = 0;
8489         rsurface.passcolor4f = NULL;
8490         rsurface.passcolor4f_vertexbuffer = NULL;
8491         rsurface.passcolor4f_bufferoffset = 0;
8492         rsurface.forcecurrenttextureupdate = true;
8493
8494         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8495         {
8496                 if ((wantnormals || wanttangents) && !normal3f)
8497                 {
8498                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8499                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8500                 }
8501                 if (wanttangents && !svector3f)
8502                 {
8503                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8504                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8505                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8506                 }
8507         }
8508 }
8509
8510 float RSurf_FogPoint(const float *v)
8511 {
8512         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8513         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8514         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8515         float FogHeightFade = r_refdef.fogheightfade;
8516         float fogfrac;
8517         unsigned int fogmasktableindex;
8518         if (r_refdef.fogplaneviewabove)
8519                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8520         else
8521                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8522         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8523         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8524 }
8525
8526 float RSurf_FogVertex(const float *v)
8527 {
8528         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8529         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8530         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8531         float FogHeightFade = rsurface.fogheightfade;
8532         float fogfrac;
8533         unsigned int fogmasktableindex;
8534         if (r_refdef.fogplaneviewabove)
8535                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8536         else
8537                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8538         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8539         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8540 }
8541
8542 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8543 {
8544         int i;
8545         for (i = 0;i < numelements;i++)
8546                 outelement3i[i] = inelement3i[i] + adjust;
8547 }
8548
8549 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8550 extern cvar_t gl_vbo;
8551 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8552 {
8553         int deformindex;
8554         int firsttriangle;
8555         int numtriangles;
8556         int firstvertex;
8557         int endvertex;
8558         int numvertices;
8559         int surfacefirsttriangle;
8560         int surfacenumtriangles;
8561         int surfacefirstvertex;
8562         int surfaceendvertex;
8563         int surfacenumvertices;
8564         int batchnumvertices;
8565         int batchnumtriangles;
8566         int needsupdate;
8567         int i, j;
8568         qboolean gaps;
8569         qboolean dynamicvertex;
8570         float amplitude;
8571         float animpos;
8572         float scale;
8573         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8574         float waveparms[4];
8575         q3shaderinfo_deform_t *deform;
8576         const msurface_t *surface, *firstsurface;
8577         r_vertexmesh_t *vertexmesh;
8578         if (!texturenumsurfaces)
8579                 return;
8580         // find vertex range of this surface batch
8581         gaps = false;
8582         firstsurface = texturesurfacelist[0];
8583         firsttriangle = firstsurface->num_firsttriangle;
8584         batchnumvertices = 0;
8585         batchnumtriangles = 0;
8586         firstvertex = endvertex = firstsurface->num_firstvertex;
8587         for (i = 0;i < texturenumsurfaces;i++)
8588         {
8589                 surface = texturesurfacelist[i];
8590                 if (surface != firstsurface + i)
8591                         gaps = true;
8592                 surfacefirstvertex = surface->num_firstvertex;
8593                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8594                 surfacenumvertices = surface->num_vertices;
8595                 surfacenumtriangles = surface->num_triangles;
8596                 if (firstvertex > surfacefirstvertex)
8597                         firstvertex = surfacefirstvertex;
8598                 if (endvertex < surfaceendvertex)
8599                         endvertex = surfaceendvertex;
8600                 batchnumvertices += surfacenumvertices;
8601                 batchnumtriangles += surfacenumtriangles;
8602         }
8603
8604         // we now know the vertex range used, and if there are any gaps in it
8605         rsurface.batchfirstvertex = firstvertex;
8606         rsurface.batchnumvertices = endvertex - firstvertex;
8607         rsurface.batchfirsttriangle = firsttriangle;
8608         rsurface.batchnumtriangles = batchnumtriangles;
8609
8610         // this variable holds flags for which properties have been updated that
8611         // may require regenerating vertexmesh array...
8612         needsupdate = 0;
8613
8614         // check if any dynamic vertex processing must occur
8615         dynamicvertex = false;
8616
8617         // if there is a chance of animated vertex colors, it's a dynamic batch
8618         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8619         {
8620                 dynamicvertex = true;
8621                 batchneed |= BATCHNEED_NOGAPS;
8622                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8623         }
8624
8625         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8626         {
8627                 switch (deform->deform)
8628                 {
8629                 default:
8630                 case Q3DEFORM_PROJECTIONSHADOW:
8631                 case Q3DEFORM_TEXT0:
8632                 case Q3DEFORM_TEXT1:
8633                 case Q3DEFORM_TEXT2:
8634                 case Q3DEFORM_TEXT3:
8635                 case Q3DEFORM_TEXT4:
8636                 case Q3DEFORM_TEXT5:
8637                 case Q3DEFORM_TEXT6:
8638                 case Q3DEFORM_TEXT7:
8639                 case Q3DEFORM_NONE:
8640                         break;
8641                 case Q3DEFORM_AUTOSPRITE:
8642                         dynamicvertex = true;
8643                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8644                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8645                         break;
8646                 case Q3DEFORM_AUTOSPRITE2:
8647                         dynamicvertex = true;
8648                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8649                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8650                         break;
8651                 case Q3DEFORM_NORMAL:
8652                         dynamicvertex = true;
8653                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8654                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8655                         break;
8656                 case Q3DEFORM_WAVE:
8657                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8658                                 break; // if wavefunc is a nop, ignore this transform
8659                         dynamicvertex = true;
8660                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8661                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8662                         break;
8663                 case Q3DEFORM_BULGE:
8664                         dynamicvertex = true;
8665                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8666                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8667                         break;
8668                 case Q3DEFORM_MOVE:
8669                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8670                                 break; // if wavefunc is a nop, ignore this transform
8671                         dynamicvertex = true;
8672                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8673                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8674                         break;
8675                 }
8676         }
8677         switch(rsurface.texture->tcgen.tcgen)
8678         {
8679         default:
8680         case Q3TCGEN_TEXTURE:
8681                 break;
8682         case Q3TCGEN_LIGHTMAP:
8683                 dynamicvertex = true;
8684                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8685                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8686                 break;
8687         case Q3TCGEN_VECTOR:
8688                 dynamicvertex = true;
8689                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8690                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8691                 break;
8692         case Q3TCGEN_ENVIRONMENT:
8693                 dynamicvertex = true;
8694                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8695                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8696                 break;
8697         }
8698         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8699         {
8700                 dynamicvertex = true;
8701                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8702                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8703         }
8704
8705         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8706         {
8707                 dynamicvertex = true;
8708                 batchneed |= BATCHNEED_NOGAPS;
8709                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8710         }
8711
8712         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8713         {
8714                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8715                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8716                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8717                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8718                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8719                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8720                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8721         }
8722
8723         // when the model data has no vertex buffer (dynamic mesh), we need to
8724         // eliminate gaps
8725         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8726                 batchneed |= BATCHNEED_NOGAPS;
8727
8728         // if needsupdate, we have to do a dynamic vertex batch for sure
8729         if (needsupdate & batchneed)
8730                 dynamicvertex = true;
8731
8732         // see if we need to build vertexmesh from arrays
8733         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8734                 dynamicvertex = true;
8735
8736         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8737         // also some drivers strongly dislike firstvertex
8738         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8739                 dynamicvertex = true;
8740
8741         rsurface.batchvertex3f = rsurface.modelvertex3f;
8742         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8743         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8744         rsurface.batchsvector3f = rsurface.modelsvector3f;
8745         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8746         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8747         rsurface.batchtvector3f = rsurface.modeltvector3f;
8748         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8749         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8750         rsurface.batchnormal3f = rsurface.modelnormal3f;
8751         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8752         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8753         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8754         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8755         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8756         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8757         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8758         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8759         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8760         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8761         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8762         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8763         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8764         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8765         rsurface.batchelement3i = rsurface.modelelement3i;
8766         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8767         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8768         rsurface.batchelement3s = rsurface.modelelement3s;
8769         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8770         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8771
8772         // if any dynamic vertex processing has to occur in software, we copy the
8773         // entire surface list together before processing to rebase the vertices
8774         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8775         //
8776         // if any gaps exist and we do not have a static vertex buffer, we have to
8777         // copy the surface list together to avoid wasting upload bandwidth on the
8778         // vertices in the gaps.
8779         //
8780         // if gaps exist and we have a static vertex buffer, we still have to
8781         // combine the index buffer ranges into one dynamic index buffer.
8782         //
8783         // in all cases we end up with data that can be drawn in one call.
8784
8785         if (!dynamicvertex)
8786         {
8787                 // static vertex data, just set pointers...
8788                 rsurface.batchgeneratedvertex = false;
8789                 // if there are gaps, we want to build a combined index buffer,
8790                 // otherwise use the original static buffer with an appropriate offset
8791                 if (gaps)
8792                 {
8793                         // build a new triangle elements array for this batch
8794                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8795                         rsurface.batchfirsttriangle = 0;
8796                         numtriangles = 0;
8797                         for (i = 0;i < texturenumsurfaces;i++)
8798                         {
8799                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8800                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8801                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8802                                 numtriangles += surfacenumtriangles;
8803                         }
8804                         rsurface.batchelement3i_indexbuffer = NULL;
8805                         rsurface.batchelement3i_bufferoffset = 0;
8806                         rsurface.batchelement3s = NULL;
8807                         rsurface.batchelement3s_indexbuffer = NULL;
8808                         rsurface.batchelement3s_bufferoffset = 0;
8809                         if (endvertex <= 65536)
8810                         {
8811                                 // make a 16bit (unsigned short) index array if possible
8812                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8813                                 for (i = 0;i < numtriangles*3;i++)
8814                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8815                         }
8816                 }
8817                 return;
8818         }
8819
8820         // something needs software processing, do it for real...
8821         // we only directly handle separate array data in this case and then
8822         // generate interleaved data if needed...
8823         rsurface.batchgeneratedvertex = true;
8824
8825         // now copy the vertex data into a combined array and make an index array
8826         // (this is what Quake3 does all the time)
8827         //if (gaps || rsurface.batchfirstvertex)
8828         {
8829                 rsurface.batchvertex3fbuffer = NULL;
8830                 rsurface.batchvertexmesh = NULL;
8831                 rsurface.batchvertexmeshbuffer = NULL;
8832                 rsurface.batchvertex3f = NULL;
8833                 rsurface.batchvertex3f_vertexbuffer = NULL;
8834                 rsurface.batchvertex3f_bufferoffset = 0;
8835                 rsurface.batchsvector3f = NULL;
8836                 rsurface.batchsvector3f_vertexbuffer = NULL;
8837                 rsurface.batchsvector3f_bufferoffset = 0;
8838                 rsurface.batchtvector3f = NULL;
8839                 rsurface.batchtvector3f_vertexbuffer = NULL;
8840                 rsurface.batchtvector3f_bufferoffset = 0;
8841                 rsurface.batchnormal3f = NULL;
8842                 rsurface.batchnormal3f_vertexbuffer = NULL;
8843                 rsurface.batchnormal3f_bufferoffset = 0;
8844                 rsurface.batchlightmapcolor4f = NULL;
8845                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8846                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8847                 rsurface.batchtexcoordtexture2f = NULL;
8848                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8849                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8850                 rsurface.batchtexcoordlightmap2f = NULL;
8851                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8852                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8853                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8854                 rsurface.batchelement3i_indexbuffer = NULL;
8855                 rsurface.batchelement3i_bufferoffset = 0;
8856                 rsurface.batchelement3s = NULL;
8857                 rsurface.batchelement3s_indexbuffer = NULL;
8858                 rsurface.batchelement3s_bufferoffset = 0;
8859                 // we'll only be setting up certain arrays as needed
8860                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8861                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8862                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8863                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8864                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8865                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8866                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8867                 {
8868                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8869                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8870                 }
8871                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8872                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8873                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8874                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8875                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8876                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8877                 numvertices = 0;
8878                 numtriangles = 0;
8879                 for (i = 0;i < texturenumsurfaces;i++)
8880                 {
8881                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8882                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8883                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8884                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8885                         // copy only the data requested
8886                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8887                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8888                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8889                         {
8890                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8891                                 {
8892                                         if (rsurface.batchvertex3f)
8893                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8894                                         else
8895                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8896                                 }
8897                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8898                                 {
8899                                         if (rsurface.modelnormal3f)
8900                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8901                                         else
8902                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8903                                 }
8904                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8905                                 {
8906                                         if (rsurface.modelsvector3f)
8907                                         {
8908                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8909                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8910                                         }
8911                                         else
8912                                         {
8913                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8914                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8915                                         }
8916                                 }
8917                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8918                                 {
8919                                         if (rsurface.modellightmapcolor4f)
8920                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8921                                         else
8922                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8923                                 }
8924                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8925                                 {
8926                                         if (rsurface.modeltexcoordtexture2f)
8927                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8928                                         else
8929                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8930                                 }
8931                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8932                                 {
8933                                         if (rsurface.modeltexcoordlightmap2f)
8934                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8935                                         else
8936                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8937                                 }
8938                         }
8939                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8940                         numvertices += surfacenumvertices;
8941                         numtriangles += surfacenumtriangles;
8942                 }
8943
8944                 // generate a 16bit index array as well if possible
8945                 // (in general, dynamic batches fit)
8946                 if (numvertices <= 65536)
8947                 {
8948                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8949                         for (i = 0;i < numtriangles*3;i++)
8950                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8951                 }
8952
8953                 // since we've copied everything, the batch now starts at 0
8954                 rsurface.batchfirstvertex = 0;
8955                 rsurface.batchnumvertices = batchnumvertices;
8956                 rsurface.batchfirsttriangle = 0;
8957                 rsurface.batchnumtriangles = batchnumtriangles;
8958         }
8959
8960         // q1bsp surfaces rendered in vertex color mode have to have colors
8961         // calculated based on lightstyles
8962         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8963         {
8964                 // generate color arrays for the surfaces in this list
8965                 int c[4];
8966                 int scale;
8967                 int size3;
8968                 const int *offsets;
8969                 const unsigned char *lm;
8970                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8971                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8972                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8973                 numvertices = 0;
8974                 for (i = 0;i < texturenumsurfaces;i++)
8975                 {
8976                         surface = texturesurfacelist[i];
8977                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8978                         surfacenumvertices = surface->num_vertices;
8979                         if (surface->lightmapinfo->samples)
8980                         {
8981                                 for (j = 0;j < surfacenumvertices;j++)
8982                                 {
8983                                         lm = surface->lightmapinfo->samples + offsets[j];
8984                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8985                                         VectorScale(lm, scale, c);
8986                                         if (surface->lightmapinfo->styles[1] != 255)
8987                                         {
8988                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8989                                                 lm += size3;
8990                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8991                                                 VectorMA(c, scale, lm, c);
8992                                                 if (surface->lightmapinfo->styles[2] != 255)
8993                                                 {
8994                                                         lm += size3;
8995                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8996                                                         VectorMA(c, scale, lm, c);
8997                                                         if (surface->lightmapinfo->styles[3] != 255)
8998                                                         {
8999                                                                 lm += size3;
9000                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
9001                                                                 VectorMA(c, scale, lm, c);
9002                                                         }
9003                                                 }
9004                                         }
9005                                         c[0] >>= 7;
9006                                         c[1] >>= 7;
9007                                         c[2] >>= 7;
9008                                         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);
9009                                         numvertices++;
9010                                 }
9011                         }
9012                         else
9013                         {
9014                                 for (j = 0;j < surfacenumvertices;j++)
9015                                 {
9016                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9017                                         numvertices++;
9018                                 }
9019                         }
9020                 }
9021         }
9022
9023         // if vertices are deformed (sprite flares and things in maps, possibly
9024         // water waves, bulges and other deformations), modify the copied vertices
9025         // in place
9026         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9027         {
9028                 switch (deform->deform)
9029                 {
9030                 default:
9031                 case Q3DEFORM_PROJECTIONSHADOW:
9032                 case Q3DEFORM_TEXT0:
9033                 case Q3DEFORM_TEXT1:
9034                 case Q3DEFORM_TEXT2:
9035                 case Q3DEFORM_TEXT3:
9036                 case Q3DEFORM_TEXT4:
9037                 case Q3DEFORM_TEXT5:
9038                 case Q3DEFORM_TEXT6:
9039                 case Q3DEFORM_TEXT7:
9040                 case Q3DEFORM_NONE:
9041                         break;
9042                 case Q3DEFORM_AUTOSPRITE:
9043                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9044                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9045                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9046                         VectorNormalize(newforward);
9047                         VectorNormalize(newright);
9048                         VectorNormalize(newup);
9049 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9050 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9051 //                      rsurface.batchvertex3f_bufferoffset = 0;
9052 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9053 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9054 //                      rsurface.batchsvector3f_bufferoffset = 0;
9055 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9056 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9057 //                      rsurface.batchtvector3f_bufferoffset = 0;
9058 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9059 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9060 //                      rsurface.batchnormal3f_bufferoffset = 0;
9061                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9062                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9063                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9064                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9065                                 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);
9066                         // a single autosprite surface can contain multiple sprites...
9067                         for (j = 0;j < batchnumvertices - 3;j += 4)
9068                         {
9069                                 VectorClear(center);
9070                                 for (i = 0;i < 4;i++)
9071                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9072                                 VectorScale(center, 0.25f, center);
9073                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9074                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9075                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9076                                 for (i = 0;i < 4;i++)
9077                                 {
9078                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9079                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9080                                 }
9081                         }
9082                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9083                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9084                         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);
9085                         break;
9086                 case Q3DEFORM_AUTOSPRITE2:
9087                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9088                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9089                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9090                         VectorNormalize(newforward);
9091                         VectorNormalize(newright);
9092                         VectorNormalize(newup);
9093 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9094 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9095 //                      rsurface.batchvertex3f_bufferoffset = 0;
9096                         {
9097                                 const float *v1, *v2;
9098                                 vec3_t start, end;
9099                                 float f, l;
9100                                 struct
9101                                 {
9102                                         float length2;
9103                                         const float *v1;
9104                                         const float *v2;
9105                                 }
9106                                 shortest[2];
9107                                 memset(shortest, 0, sizeof(shortest));
9108                                 // a single autosprite surface can contain multiple sprites...
9109                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9110                                 {
9111                                         VectorClear(center);
9112                                         for (i = 0;i < 4;i++)
9113                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9114                                         VectorScale(center, 0.25f, center);
9115                                         // find the two shortest edges, then use them to define the
9116                                         // axis vectors for rotating around the central axis
9117                                         for (i = 0;i < 6;i++)
9118                                         {
9119                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9120                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9121                                                 l = VectorDistance2(v1, v2);
9122                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9123                                                 if (v1[2] != v2[2])
9124                                                         l += (1.0f / 1024.0f);
9125                                                 if (shortest[0].length2 > l || i == 0)
9126                                                 {
9127                                                         shortest[1] = shortest[0];
9128                                                         shortest[0].length2 = l;
9129                                                         shortest[0].v1 = v1;
9130                                                         shortest[0].v2 = v2;
9131                                                 }
9132                                                 else if (shortest[1].length2 > l || i == 1)
9133                                                 {
9134                                                         shortest[1].length2 = l;
9135                                                         shortest[1].v1 = v1;
9136                                                         shortest[1].v2 = v2;
9137                                                 }
9138                                         }
9139                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9140                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9141                                         // this calculates the right vector from the shortest edge
9142                                         // and the up vector from the edge midpoints
9143                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9144                                         VectorNormalize(right);
9145                                         VectorSubtract(end, start, up);
9146                                         VectorNormalize(up);
9147                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9148                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9149                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9150                                         VectorNegate(forward, forward);
9151                                         VectorReflect(forward, 0, up, forward);
9152                                         VectorNormalize(forward);
9153                                         CrossProduct(up, forward, newright);
9154                                         VectorNormalize(newright);
9155                                         // rotate the quad around the up axis vector, this is made
9156                                         // especially easy by the fact we know the quad is flat,
9157                                         // so we only have to subtract the center position and
9158                                         // measure distance along the right vector, and then
9159                                         // multiply that by the newright vector and add back the
9160                                         // center position
9161                                         // we also need to subtract the old position to undo the
9162                                         // displacement from the center, which we do with a
9163                                         // DotProduct, the subtraction/addition of center is also
9164                                         // optimized into DotProducts here
9165                                         l = DotProduct(right, center);
9166                                         for (i = 0;i < 4;i++)
9167                                         {
9168                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9169                                                 f = DotProduct(right, v1) - l;
9170                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9171                                         }
9172                                 }
9173                         }
9174                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9175                         {
9176 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9177 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9178 //                              rsurface.batchnormal3f_bufferoffset = 0;
9179                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9180                         }
9181                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9182                         {
9183 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9184 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9185 //                              rsurface.batchsvector3f_bufferoffset = 0;
9186 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9187 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9188 //                              rsurface.batchtvector3f_bufferoffset = 0;
9189                                 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);
9190                         }
9191                         break;
9192                 case Q3DEFORM_NORMAL:
9193                         // deform the normals to make reflections wavey
9194                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9195                         rsurface.batchnormal3f_vertexbuffer = NULL;
9196                         rsurface.batchnormal3f_bufferoffset = 0;
9197                         for (j = 0;j < batchnumvertices;j++)
9198                         {
9199                                 float vertex[3];
9200                                 float *normal = rsurface.batchnormal3f + 3*j;
9201                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9202                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9203                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9204                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9205                                 VectorNormalize(normal);
9206                         }
9207                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9208                         {
9209 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9210 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9211 //                              rsurface.batchsvector3f_bufferoffset = 0;
9212 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9213 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9214 //                              rsurface.batchtvector3f_bufferoffset = 0;
9215                                 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);
9216                         }
9217                         break;
9218                 case Q3DEFORM_WAVE:
9219                         // deform vertex array to make wavey water and flags and such
9220                         waveparms[0] = deform->waveparms[0];
9221                         waveparms[1] = deform->waveparms[1];
9222                         waveparms[2] = deform->waveparms[2];
9223                         waveparms[3] = deform->waveparms[3];
9224                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9225                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9226                         // this is how a divisor of vertex influence on deformation
9227                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9228                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9229 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9230 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9231 //                      rsurface.batchvertex3f_bufferoffset = 0;
9232 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9233 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9234 //                      rsurface.batchnormal3f_bufferoffset = 0;
9235                         for (j = 0;j < batchnumvertices;j++)
9236                         {
9237                                 // if the wavefunc depends on time, evaluate it per-vertex
9238                                 if (waveparms[3])
9239                                 {
9240                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9241                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9242                                 }
9243                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9244                         }
9245                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9246                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9247                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9248                         {
9249 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9250 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9251 //                              rsurface.batchsvector3f_bufferoffset = 0;
9252 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9253 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9254 //                              rsurface.batchtvector3f_bufferoffset = 0;
9255                                 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);
9256                         }
9257                         break;
9258                 case Q3DEFORM_BULGE:
9259                         // deform vertex array to make the surface have moving bulges
9260 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9261 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9262 //                      rsurface.batchvertex3f_bufferoffset = 0;
9263 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9264 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9265 //                      rsurface.batchnormal3f_bufferoffset = 0;
9266                         for (j = 0;j < batchnumvertices;j++)
9267                         {
9268                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9269                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9270                         }
9271                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9272                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9273                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9274                         {
9275 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9276 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9277 //                              rsurface.batchsvector3f_bufferoffset = 0;
9278 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9279 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9280 //                              rsurface.batchtvector3f_bufferoffset = 0;
9281                                 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);
9282                         }
9283                         break;
9284                 case Q3DEFORM_MOVE:
9285                         // deform vertex array
9286                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9287                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9288                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9289                         VectorScale(deform->parms, scale, waveparms);
9290 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9291 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9292 //                      rsurface.batchvertex3f_bufferoffset = 0;
9293                         for (j = 0;j < batchnumvertices;j++)
9294                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9295                         break;
9296                 }
9297         }
9298
9299         // generate texcoords based on the chosen texcoord source
9300         switch(rsurface.texture->tcgen.tcgen)
9301         {
9302         default:
9303         case Q3TCGEN_TEXTURE:
9304                 break;
9305         case Q3TCGEN_LIGHTMAP:
9306 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9307 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9308 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9309                 if (rsurface.batchtexcoordlightmap2f)
9310                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9311                 break;
9312         case Q3TCGEN_VECTOR:
9313 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9314 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9315 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9316                 for (j = 0;j < batchnumvertices;j++)
9317                 {
9318                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9319                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9320                 }
9321                 break;
9322         case Q3TCGEN_ENVIRONMENT:
9323                 // make environment reflections using a spheremap
9324                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9325                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9326                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9327                 for (j = 0;j < batchnumvertices;j++)
9328                 {
9329                         // identical to Q3A's method, but executed in worldspace so
9330                         // carried models can be shiny too
9331
9332                         float viewer[3], d, reflected[3], worldreflected[3];
9333
9334                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9335                         // VectorNormalize(viewer);
9336
9337                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9338
9339                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9340                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9341                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9342                         // note: this is proportinal to viewer, so we can normalize later
9343
9344                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9345                         VectorNormalize(worldreflected);
9346
9347                         // note: this sphere map only uses world x and z!
9348                         // so positive and negative y will LOOK THE SAME.
9349                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9350                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9351                 }
9352                 break;
9353         }
9354         // the only tcmod that needs software vertex processing is turbulent, so
9355         // check for it here and apply the changes if needed
9356         // and we only support that as the first one
9357         // (handling a mixture of turbulent and other tcmods would be problematic
9358         //  without punting it entirely to a software path)
9359         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9360         {
9361                 amplitude = rsurface.texture->tcmods[0].parms[1];
9362                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9363 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9364 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9365 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9366                 for (j = 0;j < batchnumvertices;j++)
9367                 {
9368                         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);
9369                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9370                 }
9371         }
9372
9373         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9374         {
9375                 // convert the modified arrays to vertex structs
9376 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9377 //              rsurface.batchvertexmeshbuffer = NULL;
9378                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9379                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9380                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9381                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9382                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9383                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9384                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9385                 {
9386                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9387                         {
9388                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9389                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9390                         }
9391                 }
9392                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9393                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9394                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9395                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9396                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9397                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9398                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9399                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9400                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9401         }
9402 }
9403
9404 void RSurf_DrawBatch(void)
9405 {
9406         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9407         // through the pipeline, killing it earlier in the pipeline would have
9408         // per-surface overhead rather than per-batch overhead, so it's best to
9409         // reject it here, before it hits glDraw.
9410         if (rsurface.batchnumtriangles == 0)
9411                 return;
9412 #if 0
9413         // batch debugging code
9414         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9415         {
9416                 int i;
9417                 int j;
9418                 int c;
9419                 const int *e;
9420                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9421                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9422                 {
9423                         c = e[i];
9424                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9425                         {
9426                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9427                                 {
9428                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9429                                                 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);
9430                                         break;
9431                                 }
9432                         }
9433                 }
9434         }
9435 #endif
9436         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);
9437 }
9438
9439 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9440 {
9441         // pick the closest matching water plane
9442         int planeindex, vertexindex, bestplaneindex = -1;
9443         float d, bestd;
9444         vec3_t vert;
9445         const float *v;
9446         r_waterstate_waterplane_t *p;
9447         qboolean prepared = false;
9448         bestd = 0;
9449         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9450         {
9451                 if(p->camera_entity != rsurface.texture->camera_entity)
9452                         continue;
9453                 d = 0;
9454                 if(!prepared)
9455                 {
9456                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9457                         prepared = true;
9458                         if(rsurface.batchnumvertices == 0)
9459                                 break;
9460                 }
9461                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9462                 {
9463                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9464                         d += fabs(PlaneDiff(vert, &p->plane));
9465                 }
9466                 if (bestd > d || bestplaneindex < 0)
9467                 {
9468                         bestd = d;
9469                         bestplaneindex = planeindex;
9470                 }
9471         }
9472         return bestplaneindex;
9473         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9474         // this situation though, as it might be better to render single larger
9475         // batches with useless stuff (backface culled for example) than to
9476         // render multiple smaller batches
9477 }
9478
9479 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9480 {
9481         int i;
9482         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9483         rsurface.passcolor4f_vertexbuffer = 0;
9484         rsurface.passcolor4f_bufferoffset = 0;
9485         for (i = 0;i < rsurface.batchnumvertices;i++)
9486                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9487 }
9488
9489 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9490 {
9491         int i;
9492         float f;
9493         const float *v;
9494         const float *c;
9495         float *c2;
9496         if (rsurface.passcolor4f)
9497         {
9498                 // generate color arrays
9499                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9500                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9501                 rsurface.passcolor4f_vertexbuffer = 0;
9502                 rsurface.passcolor4f_bufferoffset = 0;
9503                 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)
9504                 {
9505                         f = RSurf_FogVertex(v);
9506                         c2[0] = c[0] * f;
9507                         c2[1] = c[1] * f;
9508                         c2[2] = c[2] * f;
9509                         c2[3] = c[3];
9510                 }
9511         }
9512         else
9513         {
9514                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9515                 rsurface.passcolor4f_vertexbuffer = 0;
9516                 rsurface.passcolor4f_bufferoffset = 0;
9517                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9518                 {
9519                         f = RSurf_FogVertex(v);
9520                         c2[0] = f;
9521                         c2[1] = f;
9522                         c2[2] = f;
9523                         c2[3] = 1;
9524                 }
9525         }
9526 }
9527
9528 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9529 {
9530         int i;
9531         float f;
9532         const float *v;
9533         const float *c;
9534         float *c2;
9535         if (!rsurface.passcolor4f)
9536                 return;
9537         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9538         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9539         rsurface.passcolor4f_vertexbuffer = 0;
9540         rsurface.passcolor4f_bufferoffset = 0;
9541         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)
9542         {
9543                 f = RSurf_FogVertex(v);
9544                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9545                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9546                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9547                 c2[3] = c[3];
9548         }
9549 }
9550
9551 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9552 {
9553         int i;
9554         const float *c;
9555         float *c2;
9556         if (!rsurface.passcolor4f)
9557                 return;
9558         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9559         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9560         rsurface.passcolor4f_vertexbuffer = 0;
9561         rsurface.passcolor4f_bufferoffset = 0;
9562         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9563         {
9564                 c2[0] = c[0] * r;
9565                 c2[1] = c[1] * g;
9566                 c2[2] = c[2] * b;
9567                 c2[3] = c[3] * a;
9568         }
9569 }
9570
9571 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9572 {
9573         int i;
9574         const float *c;
9575         float *c2;
9576         if (!rsurface.passcolor4f)
9577                 return;
9578         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9579         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9580         rsurface.passcolor4f_vertexbuffer = 0;
9581         rsurface.passcolor4f_bufferoffset = 0;
9582         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9583         {
9584                 c2[0] = c[0] + r_refdef.scene.ambient;
9585                 c2[1] = c[1] + r_refdef.scene.ambient;
9586                 c2[2] = c[2] + r_refdef.scene.ambient;
9587                 c2[3] = c[3];
9588         }
9589 }
9590
9591 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9592 {
9593         // TODO: optimize
9594         rsurface.passcolor4f = NULL;
9595         rsurface.passcolor4f_vertexbuffer = 0;
9596         rsurface.passcolor4f_bufferoffset = 0;
9597         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9598         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9599         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9600         GL_Color(r, g, b, a);
9601         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9602         RSurf_DrawBatch();
9603 }
9604
9605 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9606 {
9607         // TODO: optimize applyfog && applycolor case
9608         // just apply fog if necessary, and tint the fog color array if necessary
9609         rsurface.passcolor4f = NULL;
9610         rsurface.passcolor4f_vertexbuffer = 0;
9611         rsurface.passcolor4f_bufferoffset = 0;
9612         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9613         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9614         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9615         GL_Color(r, g, b, a);
9616         RSurf_DrawBatch();
9617 }
9618
9619 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9620 {
9621         // TODO: optimize
9622         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9623         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9624         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9625         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9626         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9627         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9628         GL_Color(r, g, b, a);
9629         RSurf_DrawBatch();
9630 }
9631
9632 static void RSurf_DrawBatch_GL11_ClampColor(void)
9633 {
9634         int i;
9635         const float *c1;
9636         float *c2;
9637         if (!rsurface.passcolor4f)
9638                 return;
9639         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9640         {
9641                 c2[0] = bound(0.0f, c1[0], 1.0f);
9642                 c2[1] = bound(0.0f, c1[1], 1.0f);
9643                 c2[2] = bound(0.0f, c1[2], 1.0f);
9644                 c2[3] = bound(0.0f, c1[3], 1.0f);
9645         }
9646 }
9647
9648 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9649 {
9650         int i;
9651         float f;
9652         const float *v;
9653         const float *n;
9654         float *c;
9655         //vec3_t eyedir;
9656
9657         // fake shading
9658         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9659         rsurface.passcolor4f_vertexbuffer = 0;
9660         rsurface.passcolor4f_bufferoffset = 0;
9661         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)
9662         {
9663                 f = -DotProduct(r_refdef.view.forward, n);
9664                 f = max(0, f);
9665                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9666                 f *= r_refdef.lightmapintensity;
9667                 Vector4Set(c, f, f, f, 1);
9668         }
9669 }
9670
9671 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9672 {
9673         RSurf_DrawBatch_GL11_ApplyFakeLight();
9674         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9675         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9676         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9677         GL_Color(r, g, b, a);
9678         RSurf_DrawBatch();
9679 }
9680
9681 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9682 {
9683         int i;
9684         float f;
9685         float alpha;
9686         const float *v;
9687         const float *n;
9688         float *c;
9689         vec3_t ambientcolor;
9690         vec3_t diffusecolor;
9691         vec3_t lightdir;
9692         // TODO: optimize
9693         // model lighting
9694         VectorCopy(rsurface.modellight_lightdir, lightdir);
9695         f = 0.5f * r_refdef.lightmapintensity;
9696         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9697         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9698         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9699         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9700         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9701         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9702         alpha = *a;
9703         if (VectorLength2(diffusecolor) > 0)
9704         {
9705                 // q3-style directional shading
9706                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9707                 rsurface.passcolor4f_vertexbuffer = 0;
9708                 rsurface.passcolor4f_bufferoffset = 0;
9709                 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)
9710                 {
9711                         if ((f = DotProduct(n, lightdir)) > 0)
9712                                 VectorMA(ambientcolor, f, diffusecolor, c);
9713                         else
9714                                 VectorCopy(ambientcolor, c);
9715                         c[3] = alpha;
9716                 }
9717                 *r = 1;
9718                 *g = 1;
9719                 *b = 1;
9720                 *a = 1;
9721                 *applycolor = false;
9722         }
9723         else
9724         {
9725                 *r = ambientcolor[0];
9726                 *g = ambientcolor[1];
9727                 *b = ambientcolor[2];
9728                 rsurface.passcolor4f = NULL;
9729                 rsurface.passcolor4f_vertexbuffer = 0;
9730                 rsurface.passcolor4f_bufferoffset = 0;
9731         }
9732 }
9733
9734 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9735 {
9736         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9737         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9738         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9739         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9740         GL_Color(r, g, b, a);
9741         RSurf_DrawBatch();
9742 }
9743
9744 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9745 {
9746         int i;
9747         float f;
9748         const float *v;
9749         float *c;
9750
9751         // fake shading
9752         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9753         rsurface.passcolor4f_vertexbuffer = 0;
9754         rsurface.passcolor4f_bufferoffset = 0;
9755
9756         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9757         {
9758                 f = 1 - RSurf_FogVertex(v);
9759                 c[0] = r;
9760                 c[1] = g;
9761                 c[2] = b;
9762                 c[3] = f * a;
9763         }
9764 }
9765
9766 void RSurf_SetupDepthAndCulling(void)
9767 {
9768         // submodels are biased to avoid z-fighting with world surfaces that they
9769         // may be exactly overlapping (avoids z-fighting artifacts on certain
9770         // doors and things in Quake maps)
9771         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9772         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9773         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9774         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9775 }
9776
9777 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9778 {
9779         // transparent sky would be ridiculous
9780         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9781                 return;
9782         R_SetupShader_Generic_NoTexture(false, false);
9783         skyrenderlater = true;
9784         RSurf_SetupDepthAndCulling();
9785         GL_DepthMask(true);
9786         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9787         // skymasking on them, and Quake3 never did sky masking (unlike
9788         // software Quake and software Quake2), so disable the sky masking
9789         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9790         // and skymasking also looks very bad when noclipping outside the
9791         // level, so don't use it then either.
9792         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9793         {
9794                 R_Mesh_ResetTextureState();
9795                 if (skyrendermasked)
9796                 {
9797                         R_SetupShader_DepthOrShadow(false, false);
9798                         // depth-only (masking)
9799                         GL_ColorMask(0,0,0,0);
9800                         // just to make sure that braindead drivers don't draw
9801                         // anything despite that colormask...
9802                         GL_BlendFunc(GL_ZERO, GL_ONE);
9803                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9804                         if (rsurface.batchvertex3fbuffer)
9805                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9806                         else
9807                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9808                 }
9809                 else
9810                 {
9811                         R_SetupShader_Generic_NoTexture(false, false);
9812                         // fog sky
9813                         GL_BlendFunc(GL_ONE, GL_ZERO);
9814                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9815                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9816                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9817                 }
9818                 RSurf_DrawBatch();
9819                 if (skyrendermasked)
9820                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9821         }
9822         R_Mesh_ResetTextureState();
9823         GL_Color(1, 1, 1, 1);
9824 }
9825
9826 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9827 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9828 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9829 {
9830         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9831                 return;
9832         if (prepass)
9833         {
9834                 // render screenspace normalmap to texture
9835                 GL_DepthMask(true);
9836                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9837                 RSurf_DrawBatch();
9838                 return;
9839         }
9840
9841         // bind lightmap texture
9842
9843         // water/refraction/reflection/camera surfaces have to be handled specially
9844         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9845         {
9846                 int start, end, startplaneindex;
9847                 for (start = 0;start < texturenumsurfaces;start = end)
9848                 {
9849                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9850                         if(startplaneindex < 0)
9851                         {
9852                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9853                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9854                                 end = start + 1;
9855                                 continue;
9856                         }
9857                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9858                                 ;
9859                         // now that we have a batch using the same planeindex, render it
9860                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9861                         {
9862                                 // render water or distortion background
9863                                 GL_DepthMask(true);
9864                                 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);
9865                                 RSurf_DrawBatch();
9866                                 // blend surface on top
9867                                 GL_DepthMask(false);
9868                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9869                                 RSurf_DrawBatch();
9870                         }
9871                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9872                         {
9873                                 // render surface with reflection texture as input
9874                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9875                                 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);
9876                                 RSurf_DrawBatch();
9877                         }
9878                 }
9879                 return;
9880         }
9881
9882         // render surface batch normally
9883         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9884         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);
9885         RSurf_DrawBatch();
9886 }
9887
9888 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9889 {
9890         // OpenGL 1.3 path - anything not completely ancient
9891         qboolean applycolor;
9892         qboolean applyfog;
9893         int layerindex;
9894         const texturelayer_t *layer;
9895         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);
9896         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9897
9898         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9899         {
9900                 vec4_t layercolor;
9901                 int layertexrgbscale;
9902                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9903                 {
9904                         if (layerindex == 0)
9905                                 GL_AlphaTest(true);
9906                         else
9907                         {
9908                                 GL_AlphaTest(false);
9909                                 GL_DepthFunc(GL_EQUAL);
9910                         }
9911                 }
9912                 GL_DepthMask(layer->depthmask && writedepth);
9913                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9914                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9915                 {
9916                         layertexrgbscale = 4;
9917                         VectorScale(layer->color, 0.25f, layercolor);
9918                 }
9919                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9920                 {
9921                         layertexrgbscale = 2;
9922                         VectorScale(layer->color, 0.5f, layercolor);
9923                 }
9924                 else
9925                 {
9926                         layertexrgbscale = 1;
9927                         VectorScale(layer->color, 1.0f, layercolor);
9928                 }
9929                 layercolor[3] = layer->color[3];
9930                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9931                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9932                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9933                 switch (layer->type)
9934                 {
9935                 case TEXTURELAYERTYPE_LITTEXTURE:
9936                         // single-pass lightmapped texture with 2x rgbscale
9937                         R_Mesh_TexBind(0, r_texture_white);
9938                         R_Mesh_TexMatrix(0, NULL);
9939                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9940                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9941                         R_Mesh_TexBind(1, layer->texture);
9942                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9943                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9944                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9945                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9946                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9947                         else if (FAKELIGHT_ENABLED)
9948                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9949                         else if (rsurface.uselightmaptexture)
9950                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9951                         else
9952                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9953                         break;
9954                 case TEXTURELAYERTYPE_TEXTURE:
9955                         // singletexture unlit texture with transparency support
9956                         R_Mesh_TexBind(0, layer->texture);
9957                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9958                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9959                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9960                         R_Mesh_TexBind(1, 0);
9961                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9962                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9963                         break;
9964                 case TEXTURELAYERTYPE_FOG:
9965                         // singletexture fogging
9966                         if (layer->texture)
9967                         {
9968                                 R_Mesh_TexBind(0, layer->texture);
9969                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9970                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9971                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9972                         }
9973                         else
9974                         {
9975                                 R_Mesh_TexBind(0, 0);
9976                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9977                         }
9978                         R_Mesh_TexBind(1, 0);
9979                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9980                         // generate a color array for the fog pass
9981                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9982                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9983                         RSurf_DrawBatch();
9984                         break;
9985                 default:
9986                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9987                 }
9988         }
9989         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9990         {
9991                 GL_DepthFunc(GL_LEQUAL);
9992                 GL_AlphaTest(false);
9993         }
9994 }
9995
9996 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9997 {
9998         // OpenGL 1.1 - crusty old voodoo path
9999         qboolean applyfog;
10000         int layerindex;
10001         const texturelayer_t *layer;
10002         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);
10003         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
10004
10005         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
10006         {
10007                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10008                 {
10009                         if (layerindex == 0)
10010                                 GL_AlphaTest(true);
10011                         else
10012                         {
10013                                 GL_AlphaTest(false);
10014                                 GL_DepthFunc(GL_EQUAL);
10015                         }
10016                 }
10017                 GL_DepthMask(layer->depthmask && writedepth);
10018                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10019                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10020                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10021                 switch (layer->type)
10022                 {
10023                 case TEXTURELAYERTYPE_LITTEXTURE:
10024                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))
10025                         {
10026                                 // two-pass lit texture with 2x rgbscale
10027                                 // first the lightmap pass
10028                                 R_Mesh_TexBind(0, r_texture_white);
10029                                 R_Mesh_TexMatrix(0, NULL);
10030                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10031                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10032                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10033                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10034                                 else if (FAKELIGHT_ENABLED)
10035                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10036                                 else if (rsurface.uselightmaptexture)
10037                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10038                                 else
10039                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10040                                 // then apply the texture to it
10041                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10042                                 R_Mesh_TexBind(0, layer->texture);
10043                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10044                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10045                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10046                                 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);
10047                         }
10048                         else
10049                         {
10050                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10051                                 R_Mesh_TexBind(0, layer->texture);
10052                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10053                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10054                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10055                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10056                                         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);
10057                                 else if (FAKELIGHT_ENABLED)
10058                                         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);
10059                                 else
10060                                         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);
10061                         }
10062                         break;
10063                 case TEXTURELAYERTYPE_TEXTURE:
10064                         // singletexture unlit texture with transparency support
10065                         R_Mesh_TexBind(0, layer->texture);
10066                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10067                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10068                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10069                         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);
10070                         break;
10071                 case TEXTURELAYERTYPE_FOG:
10072                         // singletexture fogging
10073                         if (layer->texture)
10074                         {
10075                                 R_Mesh_TexBind(0, layer->texture);
10076                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10077                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10078                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10079                         }
10080                         else
10081                         {
10082                                 R_Mesh_TexBind(0, 0);
10083                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10084                         }
10085                         // generate a color array for the fog pass
10086                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10087                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10088                         RSurf_DrawBatch();
10089                         break;
10090                 default:
10091                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10092                 }
10093         }
10094         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10095         {
10096                 GL_DepthFunc(GL_LEQUAL);
10097                 GL_AlphaTest(false);
10098         }
10099 }
10100
10101 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10102 {
10103         int vi;
10104         int j;
10105         r_vertexgeneric_t *batchvertex;
10106         float c[4];
10107
10108 //      R_Mesh_ResetTextureState();
10109         R_SetupShader_Generic_NoTexture(false, false);
10110
10111         if(rsurface.texture && rsurface.texture->currentskinframe)
10112         {
10113                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10114                 c[3] *= rsurface.texture->currentalpha;
10115         }
10116         else
10117         {
10118                 c[0] = 1;
10119                 c[1] = 0;
10120                 c[2] = 1;
10121                 c[3] = 1;
10122         }
10123
10124         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10125         {
10126                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10127                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10128                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10129         }
10130
10131         // brighten it up (as texture value 127 means "unlit")
10132         c[0] *= 2 * r_refdef.view.colorscale;
10133         c[1] *= 2 * r_refdef.view.colorscale;
10134         c[2] *= 2 * r_refdef.view.colorscale;
10135
10136         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10137                 c[3] *= r_wateralpha.value;
10138
10139         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10140         {
10141                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10142                 GL_DepthMask(false);
10143         }
10144         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10145         {
10146                 GL_BlendFunc(GL_ONE, GL_ONE);
10147                 GL_DepthMask(false);
10148         }
10149         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10150         {
10151                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10152                 GL_DepthMask(false);
10153         }
10154         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10155         {
10156                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10157                 GL_DepthMask(false);
10158         }
10159         else
10160         {
10161                 GL_BlendFunc(GL_ONE, GL_ZERO);
10162                 GL_DepthMask(writedepth);
10163         }
10164
10165         if (r_showsurfaces.integer == 3)
10166         {
10167                 rsurface.passcolor4f = NULL;
10168
10169                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10170                 {
10171                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10172
10173                         rsurface.passcolor4f = NULL;
10174                         rsurface.passcolor4f_vertexbuffer = 0;
10175                         rsurface.passcolor4f_bufferoffset = 0;
10176                 }
10177                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10178                 {
10179                         qboolean applycolor = true;
10180                         float one = 1.0;
10181
10182                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10183
10184                         r_refdef.lightmapintensity = 1;
10185                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10186                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10187                 }
10188                 else if (FAKELIGHT_ENABLED)
10189                 {
10190                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10191
10192                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10193                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10194                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10195                 }
10196                 else
10197                 {
10198                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10199
10200                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10201                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10202                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10203                 }
10204
10205                 if(!rsurface.passcolor4f)
10206                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10207
10208                 RSurf_DrawBatch_GL11_ApplyAmbient();
10209                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10210                 if(r_refdef.fogenabled)
10211                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10212                 RSurf_DrawBatch_GL11_ClampColor();
10213
10214                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10215                 R_SetupShader_Generic_NoTexture(false, false);
10216                 RSurf_DrawBatch();
10217         }
10218         else if (!r_refdef.view.showdebug)
10219         {
10220                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10221                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10222                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10223                 {
10224                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10225                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10226                 }
10227                 R_Mesh_PrepareVertices_Generic_Unlock();
10228                 RSurf_DrawBatch();
10229         }
10230         else if (r_showsurfaces.integer == 4)
10231         {
10232                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10233                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10234                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10235                 {
10236                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10237                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10238                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10239                 }
10240                 R_Mesh_PrepareVertices_Generic_Unlock();
10241                 RSurf_DrawBatch();
10242         }
10243         else if (r_showsurfaces.integer == 2)
10244         {
10245                 const int *e;
10246                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10247                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10248                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10249                 {
10250                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10251                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10252                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10253                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10254                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10255                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10256                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10257                 }
10258                 R_Mesh_PrepareVertices_Generic_Unlock();
10259                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10260         }
10261         else
10262         {
10263                 int texturesurfaceindex;
10264                 int k;
10265                 const msurface_t *surface;
10266                 float surfacecolor4f[4];
10267                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10268                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10269                 vi = 0;
10270                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10271                 {
10272                         surface = texturesurfacelist[texturesurfaceindex];
10273                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10274                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10275                         for (j = 0;j < surface->num_vertices;j++)
10276                         {
10277                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10278                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10279                                 vi++;
10280                         }
10281                 }
10282                 R_Mesh_PrepareVertices_Generic_Unlock();
10283                 RSurf_DrawBatch();
10284         }
10285 }
10286
10287 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10288 {
10289         CHECKGLERROR
10290         RSurf_SetupDepthAndCulling();
10291         if (r_showsurfaces.integer)
10292         {
10293                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10294                 return;
10295         }
10296         switch (vid.renderpath)
10297         {
10298         case RENDERPATH_GL20:
10299         case RENDERPATH_D3D9:
10300         case RENDERPATH_D3D10:
10301         case RENDERPATH_D3D11:
10302         case RENDERPATH_SOFT:
10303         case RENDERPATH_GLES2:
10304                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10305                 break;
10306         case RENDERPATH_GL13:
10307         case RENDERPATH_GLES1:
10308                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10309                 break;
10310         case RENDERPATH_GL11:
10311                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10312                 break;
10313         }
10314         CHECKGLERROR
10315 }
10316
10317 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10318 {
10319         CHECKGLERROR
10320         RSurf_SetupDepthAndCulling();
10321         if (r_showsurfaces.integer)
10322         {
10323                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10324                 return;
10325         }
10326         switch (vid.renderpath)
10327         {
10328         case RENDERPATH_GL20:
10329         case RENDERPATH_D3D9:
10330         case RENDERPATH_D3D10:
10331         case RENDERPATH_D3D11:
10332         case RENDERPATH_SOFT:
10333         case RENDERPATH_GLES2:
10334                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10335                 break;
10336         case RENDERPATH_GL13:
10337         case RENDERPATH_GLES1:
10338                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10339                 break;
10340         case RENDERPATH_GL11:
10341                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10342                 break;
10343         }
10344         CHECKGLERROR
10345 }
10346
10347 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10348 {
10349         int i, j;
10350         int texturenumsurfaces, endsurface;
10351         texture_t *texture;
10352         const msurface_t *surface;
10353         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10354
10355         // if the model is static it doesn't matter what value we give for
10356         // wantnormals and wanttangents, so this logic uses only rules applicable
10357         // to a model, knowing that they are meaningless otherwise
10358         if (ent == r_refdef.scene.worldentity)
10359                 RSurf_ActiveWorldEntity();
10360         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10361                 RSurf_ActiveModelEntity(ent, false, false, false);
10362         else
10363         {
10364                 switch (vid.renderpath)
10365                 {
10366                 case RENDERPATH_GL20:
10367                 case RENDERPATH_D3D9:
10368                 case RENDERPATH_D3D10:
10369                 case RENDERPATH_D3D11:
10370                 case RENDERPATH_SOFT:
10371                 case RENDERPATH_GLES2:
10372                         RSurf_ActiveModelEntity(ent, true, true, false);
10373                         break;
10374                 case RENDERPATH_GL11:
10375                 case RENDERPATH_GL13:
10376                 case RENDERPATH_GLES1:
10377                         RSurf_ActiveModelEntity(ent, true, false, false);
10378                         break;
10379                 }
10380         }
10381
10382         if (r_transparentdepthmasking.integer)
10383         {
10384                 qboolean setup = false;
10385                 for (i = 0;i < numsurfaces;i = j)
10386                 {
10387                         j = i + 1;
10388                         surface = rsurface.modelsurfaces + surfacelist[i];
10389                         texture = surface->texture;
10390                         rsurface.texture = R_GetCurrentTexture(texture);
10391                         rsurface.lightmaptexture = NULL;
10392                         rsurface.deluxemaptexture = NULL;
10393                         rsurface.uselightmaptexture = false;
10394                         // scan ahead until we find a different texture
10395                         endsurface = min(i + 1024, numsurfaces);
10396                         texturenumsurfaces = 0;
10397                         texturesurfacelist[texturenumsurfaces++] = surface;
10398                         for (;j < endsurface;j++)
10399                         {
10400                                 surface = rsurface.modelsurfaces + surfacelist[j];
10401                                 if (texture != surface->texture)
10402                                         break;
10403                                 texturesurfacelist[texturenumsurfaces++] = surface;
10404                         }
10405                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10406                                 continue;
10407                         // render the range of surfaces as depth
10408                         if (!setup)
10409                         {
10410                                 setup = true;
10411                                 GL_ColorMask(0,0,0,0);
10412                                 GL_Color(1,1,1,1);
10413                                 GL_DepthTest(true);
10414                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10415                                 GL_DepthMask(true);
10416 //                              R_Mesh_ResetTextureState();
10417                                 R_SetupShader_DepthOrShadow(false, false);
10418                         }
10419                         RSurf_SetupDepthAndCulling();
10420                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10421                         if (rsurface.batchvertex3fbuffer)
10422                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10423                         else
10424                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10425                         RSurf_DrawBatch();
10426                 }
10427                 if (setup)
10428                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10429         }
10430
10431         for (i = 0;i < numsurfaces;i = j)
10432         {
10433                 j = i + 1;
10434                 surface = rsurface.modelsurfaces + surfacelist[i];
10435                 texture = surface->texture;
10436                 rsurface.texture = R_GetCurrentTexture(texture);
10437                 // scan ahead until we find a different texture
10438                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10439                 texturenumsurfaces = 0;
10440                 texturesurfacelist[texturenumsurfaces++] = surface;
10441                 if(FAKELIGHT_ENABLED)
10442                 {
10443                         rsurface.lightmaptexture = NULL;
10444                         rsurface.deluxemaptexture = NULL;
10445                         rsurface.uselightmaptexture = false;
10446                         for (;j < endsurface;j++)
10447                         {
10448                                 surface = rsurface.modelsurfaces + surfacelist[j];
10449                                 if (texture != surface->texture)
10450                                         break;
10451                                 texturesurfacelist[texturenumsurfaces++] = surface;
10452                         }
10453                 }
10454                 else
10455                 {
10456                         rsurface.lightmaptexture = surface->lightmaptexture;
10457                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10458                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10459                         for (;j < endsurface;j++)
10460                         {
10461                                 surface = rsurface.modelsurfaces + surfacelist[j];
10462                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10463                                         break;
10464                                 texturesurfacelist[texturenumsurfaces++] = surface;
10465                         }
10466                 }
10467                 // render the range of surfaces
10468                 if (ent == r_refdef.scene.worldentity)
10469                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10470                 else
10471                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10472         }
10473         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10474 }
10475
10476 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10477 {
10478         // transparent surfaces get pushed off into the transparent queue
10479         int surfacelistindex;
10480         const msurface_t *surface;
10481         vec3_t tempcenter, center;
10482         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10483         {
10484                 surface = texturesurfacelist[surfacelistindex];
10485                 if (r_transparent_sortsurfacesbynearest.integer)
10486                 {
10487                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10488                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10489                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10490                 }
10491                 else
10492                 {
10493                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10494                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10495                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10496                 }
10497                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10498                 if (rsurface.entity->transparent_offset) // transparent offset
10499                 {
10500                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10501                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10502                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10503                 }
10504                 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);
10505         }
10506 }
10507
10508 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10509 {
10510         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10511                 return;
10512         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10513                 return;
10514         RSurf_SetupDepthAndCulling();
10515         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10516         if (rsurface.batchvertex3fbuffer)
10517                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10518         else
10519                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10520         RSurf_DrawBatch();
10521 }
10522
10523 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10524 {
10525         CHECKGLERROR
10526         if (depthonly)
10527                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10528         else if (prepass)
10529         {
10530                 if (!rsurface.texture->currentnumlayers)
10531                         return;
10532                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10533                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10534                 else
10535                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10536         }
10537         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10538                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10539         else if (!rsurface.texture->currentnumlayers)
10540                 return;
10541         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10542         {
10543                 // in the deferred case, transparent surfaces were queued during prepass
10544                 if (!r_shadow_usingdeferredprepass)
10545                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10546         }
10547         else
10548         {
10549                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10550                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10551         }
10552         CHECKGLERROR
10553 }
10554
10555 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10556 {
10557         int i, j;
10558         texture_t *texture;
10559         R_FrameData_SetMark();
10560         // break the surface list down into batches by texture and use of lightmapping
10561         for (i = 0;i < numsurfaces;i = j)
10562         {
10563                 j = i + 1;
10564                 // texture is the base texture pointer, rsurface.texture is the
10565                 // current frame/skin the texture is directing us to use (for example
10566                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10567                 // use skin 1 instead)
10568                 texture = surfacelist[i]->texture;
10569                 rsurface.texture = R_GetCurrentTexture(texture);
10570                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10571                 {
10572                         // if this texture is not the kind we want, skip ahead to the next one
10573                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10574                                 ;
10575                         continue;
10576                 }
10577                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10578                 {
10579                         rsurface.lightmaptexture = NULL;
10580                         rsurface.deluxemaptexture = NULL;
10581                         rsurface.uselightmaptexture = false;
10582                         // simply scan ahead until we find a different texture or lightmap state
10583                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10584                                 ;
10585                 }
10586                 else
10587                 {
10588                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10589                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10590                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10591                         // simply scan ahead until we find a different texture or lightmap state
10592                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10593                                 ;
10594                 }
10595                 // render the range of surfaces
10596                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10597         }
10598         R_FrameData_ReturnToMark();
10599 }
10600
10601 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10602 {
10603         CHECKGLERROR
10604         if (depthonly)
10605                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10606         else if (prepass)
10607         {
10608                 if (!rsurface.texture->currentnumlayers)
10609                         return;
10610                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10611                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10612                 else
10613                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10614         }
10615         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10616                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10617         else if (!rsurface.texture->currentnumlayers)
10618                 return;
10619         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10620         {
10621                 // in the deferred case, transparent surfaces were queued during prepass
10622                 if (!r_shadow_usingdeferredprepass)
10623                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10624         }
10625         else
10626         {
10627                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10628                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10629         }
10630         CHECKGLERROR
10631 }
10632
10633 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10634 {
10635         int i, j;
10636         texture_t *texture;
10637         R_FrameData_SetMark();
10638         // break the surface list down into batches by texture and use of lightmapping
10639         for (i = 0;i < numsurfaces;i = j)
10640         {
10641                 j = i + 1;
10642                 // texture is the base texture pointer, rsurface.texture is the
10643                 // current frame/skin the texture is directing us to use (for example
10644                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10645                 // use skin 1 instead)
10646                 texture = surfacelist[i]->texture;
10647                 rsurface.texture = R_GetCurrentTexture(texture);
10648                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10649                 {
10650                         // if this texture is not the kind we want, skip ahead to the next one
10651                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10652                                 ;
10653                         continue;
10654                 }
10655                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10656                 {
10657                         rsurface.lightmaptexture = NULL;
10658                         rsurface.deluxemaptexture = NULL;
10659                         rsurface.uselightmaptexture = false;
10660                         // simply scan ahead until we find a different texture or lightmap state
10661                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10662                                 ;
10663                 }
10664                 else
10665                 {
10666                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10667                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10668                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10669                         // simply scan ahead until we find a different texture or lightmap state
10670                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10671                                 ;
10672                 }
10673                 // render the range of surfaces
10674                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10675         }
10676         R_FrameData_ReturnToMark();
10677 }
10678
10679 float locboxvertex3f[6*4*3] =
10680 {
10681         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10682         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10683         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10684         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10685         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10686         1,0,0, 0,0,0, 0,1,0, 1,1,0
10687 };
10688
10689 unsigned short locboxelements[6*2*3] =
10690 {
10691          0, 1, 2, 0, 2, 3,
10692          4, 5, 6, 4, 6, 7,
10693          8, 9,10, 8,10,11,
10694         12,13,14, 12,14,15,
10695         16,17,18, 16,18,19,
10696         20,21,22, 20,22,23
10697 };
10698
10699 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10700 {
10701         int i, j;
10702         cl_locnode_t *loc = (cl_locnode_t *)ent;
10703         vec3_t mins, size;
10704         float vertex3f[6*4*3];
10705         CHECKGLERROR
10706         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10707         GL_DepthMask(false);
10708         GL_DepthRange(0, 1);
10709         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10710         GL_DepthTest(true);
10711         GL_CullFace(GL_NONE);
10712         R_EntityMatrix(&identitymatrix);
10713
10714 //      R_Mesh_ResetTextureState();
10715
10716         i = surfacelist[0];
10717         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10718                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10719                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10720                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10721
10722         if (VectorCompare(loc->mins, loc->maxs))
10723         {
10724                 VectorSet(size, 2, 2, 2);
10725                 VectorMA(loc->mins, -0.5f, size, mins);
10726         }
10727         else
10728         {
10729                 VectorCopy(loc->mins, mins);
10730                 VectorSubtract(loc->maxs, loc->mins, size);
10731         }
10732
10733         for (i = 0;i < 6*4*3;)
10734                 for (j = 0;j < 3;j++, i++)
10735                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10736
10737         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10738         R_SetupShader_Generic_NoTexture(false, false);
10739         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10740 }
10741
10742 void R_DrawLocs(void)
10743 {
10744         int index;
10745         cl_locnode_t *loc, *nearestloc;
10746         vec3_t center;
10747         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10748         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10749         {
10750                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10751                 R_MeshQueue_AddTransparent(TRANSPARENTSORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10752         }
10753 }
10754
10755 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10756 {
10757         if (decalsystem->decals)
10758                 Mem_Free(decalsystem->decals);
10759         memset(decalsystem, 0, sizeof(*decalsystem));
10760 }
10761
10762 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)
10763 {
10764         tridecal_t *decal;
10765         tridecal_t *decals;
10766         int i;
10767
10768         // expand or initialize the system
10769         if (decalsystem->maxdecals <= decalsystem->numdecals)
10770         {
10771                 decalsystem_t old = *decalsystem;
10772                 qboolean useshortelements;
10773                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10774                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10775                 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)));
10776                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10777                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10778                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10779                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10780                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10781                 if (decalsystem->numdecals)
10782                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10783                 if (old.decals)
10784                         Mem_Free(old.decals);
10785                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10786                         decalsystem->element3i[i] = i;
10787                 if (useshortelements)
10788                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10789                                 decalsystem->element3s[i] = i;
10790         }
10791
10792         // grab a decal and search for another free slot for the next one
10793         decals = decalsystem->decals;
10794         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10795         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10796                 ;
10797         decalsystem->freedecal = i;
10798         if (decalsystem->numdecals <= i)
10799                 decalsystem->numdecals = i + 1;
10800
10801         // initialize the decal
10802         decal->lived = 0;
10803         decal->triangleindex = triangleindex;
10804         decal->surfaceindex = surfaceindex;
10805         decal->decalsequence = decalsequence;
10806         decal->color4f[0][0] = c0[0];
10807         decal->color4f[0][1] = c0[1];
10808         decal->color4f[0][2] = c0[2];
10809         decal->color4f[0][3] = 1;
10810         decal->color4f[1][0] = c1[0];
10811         decal->color4f[1][1] = c1[1];
10812         decal->color4f[1][2] = c1[2];
10813         decal->color4f[1][3] = 1;
10814         decal->color4f[2][0] = c2[0];
10815         decal->color4f[2][1] = c2[1];
10816         decal->color4f[2][2] = c2[2];
10817         decal->color4f[2][3] = 1;
10818         decal->vertex3f[0][0] = v0[0];
10819         decal->vertex3f[0][1] = v0[1];
10820         decal->vertex3f[0][2] = v0[2];
10821         decal->vertex3f[1][0] = v1[0];
10822         decal->vertex3f[1][1] = v1[1];
10823         decal->vertex3f[1][2] = v1[2];
10824         decal->vertex3f[2][0] = v2[0];
10825         decal->vertex3f[2][1] = v2[1];
10826         decal->vertex3f[2][2] = v2[2];
10827         decal->texcoord2f[0][0] = t0[0];
10828         decal->texcoord2f[0][1] = t0[1];
10829         decal->texcoord2f[1][0] = t1[0];
10830         decal->texcoord2f[1][1] = t1[1];
10831         decal->texcoord2f[2][0] = t2[0];
10832         decal->texcoord2f[2][1] = t2[1];
10833         TriangleNormal(v0, v1, v2, decal->plane);
10834         VectorNormalize(decal->plane);
10835         decal->plane[3] = DotProduct(v0, decal->plane);
10836 }
10837
10838 extern cvar_t cl_decals_bias;
10839 extern cvar_t cl_decals_models;
10840 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10841 // baseparms, parms, temps
10842 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)
10843 {
10844         int cornerindex;
10845         int index;
10846         float v[9][3];
10847         const float *vertex3f;
10848         const float *normal3f;
10849         int numpoints;
10850         float points[2][9][3];
10851         float temp[3];
10852         float tc[9][2];
10853         float f;
10854         float c[9][4];
10855         const int *e;
10856
10857         e = rsurface.modelelement3i + 3*triangleindex;
10858
10859         vertex3f = rsurface.modelvertex3f;
10860         normal3f = rsurface.modelnormal3f;
10861
10862         if (normal3f)
10863         {
10864                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10865                 {
10866                         index = 3*e[cornerindex];
10867                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10868                 }
10869         }
10870         else
10871         {
10872                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10873                 {
10874                         index = 3*e[cornerindex];
10875                         VectorCopy(vertex3f + index, v[cornerindex]);
10876                 }
10877         }
10878
10879         // cull backfaces
10880         //TriangleNormal(v[0], v[1], v[2], normal);
10881         //if (DotProduct(normal, localnormal) < 0.0f)
10882         //      continue;
10883         // clip by each of the box planes formed from the projection matrix
10884         // if anything survives, we emit the decal
10885         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]);
10886         if (numpoints < 3)
10887                 return;
10888         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]);
10889         if (numpoints < 3)
10890                 return;
10891         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]);
10892         if (numpoints < 3)
10893                 return;
10894         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]);
10895         if (numpoints < 3)
10896                 return;
10897         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]);
10898         if (numpoints < 3)
10899                 return;
10900         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]);
10901         if (numpoints < 3)
10902                 return;
10903         // some part of the triangle survived, so we have to accept it...
10904         if (dynamic)
10905         {
10906                 // dynamic always uses the original triangle
10907                 numpoints = 3;
10908                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10909                 {
10910                         index = 3*e[cornerindex];
10911                         VectorCopy(vertex3f + index, v[cornerindex]);
10912                 }
10913         }
10914         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10915         {
10916                 // convert vertex positions to texcoords
10917                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10918                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10919                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10920                 // calculate distance fade from the projection origin
10921                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10922                 f = bound(0.0f, f, 1.0f);
10923                 c[cornerindex][0] = r * f;
10924                 c[cornerindex][1] = g * f;
10925                 c[cornerindex][2] = b * f;
10926                 c[cornerindex][3] = 1.0f;
10927                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10928         }
10929         if (dynamic)
10930                 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);
10931         else
10932                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10933                         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);
10934 }
10935 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)
10936 {
10937         matrix4x4_t projection;
10938         decalsystem_t *decalsystem;
10939         qboolean dynamic;
10940         dp_model_t *model;
10941         const msurface_t *surface;
10942         const msurface_t *surfaces;
10943         const int *surfacelist;
10944         const texture_t *texture;
10945         int numtriangles;
10946         int numsurfacelist;
10947         int surfacelistindex;
10948         int surfaceindex;
10949         int triangleindex;
10950         float localorigin[3];
10951         float localnormal[3];
10952         float localmins[3];
10953         float localmaxs[3];
10954         float localsize;
10955         //float normal[3];
10956         float planes[6][4];
10957         float angles[3];
10958         bih_t *bih;
10959         int bih_triangles_count;
10960         int bih_triangles[256];
10961         int bih_surfaces[256];
10962
10963         decalsystem = &ent->decalsystem;
10964         model = ent->model;
10965         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10966         {
10967                 R_DecalSystem_Reset(&ent->decalsystem);
10968                 return;
10969         }
10970
10971         if (!model->brush.data_leafs && !cl_decals_models.integer)
10972         {
10973                 if (decalsystem->model)
10974                         R_DecalSystem_Reset(decalsystem);
10975                 return;
10976         }
10977
10978         if (decalsystem->model != model)
10979                 R_DecalSystem_Reset(decalsystem);
10980         decalsystem->model = model;
10981
10982         RSurf_ActiveModelEntity(ent, true, false, false);
10983
10984         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10985         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10986         VectorNormalize(localnormal);
10987         localsize = worldsize*rsurface.inversematrixscale;
10988         localmins[0] = localorigin[0] - localsize;
10989         localmins[1] = localorigin[1] - localsize;
10990         localmins[2] = localorigin[2] - localsize;
10991         localmaxs[0] = localorigin[0] + localsize;
10992         localmaxs[1] = localorigin[1] + localsize;
10993         localmaxs[2] = localorigin[2] + localsize;
10994
10995         //VectorCopy(localnormal, planes[4]);
10996         //VectorVectors(planes[4], planes[2], planes[0]);
10997         AnglesFromVectors(angles, localnormal, NULL, false);
10998         AngleVectors(angles, planes[0], planes[2], planes[4]);
10999         VectorNegate(planes[0], planes[1]);
11000         VectorNegate(planes[2], planes[3]);
11001         VectorNegate(planes[4], planes[5]);
11002         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
11003         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
11004         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
11005         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
11006         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
11007         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
11008
11009 #if 1
11010 // works
11011 {
11012         matrix4x4_t forwardprojection;
11013         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11014         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11015 }
11016 #else
11017 // broken
11018 {
11019         float projectionvector[4][3];
11020         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11021         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11022         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11023         projectionvector[0][0] = planes[0][0] * ilocalsize;
11024         projectionvector[0][1] = planes[1][0] * ilocalsize;
11025         projectionvector[0][2] = planes[2][0] * ilocalsize;
11026         projectionvector[1][0] = planes[0][1] * ilocalsize;
11027         projectionvector[1][1] = planes[1][1] * ilocalsize;
11028         projectionvector[1][2] = planes[2][1] * ilocalsize;
11029         projectionvector[2][0] = planes[0][2] * ilocalsize;
11030         projectionvector[2][1] = planes[1][2] * ilocalsize;
11031         projectionvector[2][2] = planes[2][2] * ilocalsize;
11032         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11033         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11034         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11035         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11036 }
11037 #endif
11038
11039         dynamic = model->surfmesh.isanimated;
11040         numsurfacelist = model->nummodelsurfaces;
11041         surfacelist = model->sortedmodelsurfaces;
11042         surfaces = model->data_surfaces;
11043
11044         bih = NULL;
11045         bih_triangles_count = -1;
11046         if(!dynamic)
11047         {
11048                 if(model->render_bih.numleafs)
11049                         bih = &model->render_bih;
11050                 else if(model->collision_bih.numleafs)
11051                         bih = &model->collision_bih;
11052         }
11053         if(bih)
11054                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11055         if(bih_triangles_count == 0)
11056                 return;
11057         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11058                 return;
11059         if(bih_triangles_count > 0)
11060         {
11061                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11062                 {
11063                         surfaceindex = bih_surfaces[triangleindex];
11064                         surface = surfaces + surfaceindex;
11065                         texture = surface->texture;
11066                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11067                                 continue;
11068                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11069                                 continue;
11070                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11071                 }
11072         }
11073         else
11074         {
11075                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11076                 {
11077                         surfaceindex = surfacelist[surfacelistindex];
11078                         surface = surfaces + surfaceindex;
11079                         // check cull box first because it rejects more than any other check
11080                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11081                                 continue;
11082                         // skip transparent surfaces
11083                         texture = surface->texture;
11084                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11085                                 continue;
11086                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11087                                 continue;
11088                         numtriangles = surface->num_triangles;
11089                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11090                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11091                 }
11092         }
11093 }
11094
11095 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11096 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)
11097 {
11098         int renderentityindex;
11099         float worldmins[3];
11100         float worldmaxs[3];
11101         entity_render_t *ent;
11102
11103         if (!cl_decals_newsystem.integer)
11104                 return;
11105
11106         worldmins[0] = worldorigin[0] - worldsize;
11107         worldmins[1] = worldorigin[1] - worldsize;
11108         worldmins[2] = worldorigin[2] - worldsize;
11109         worldmaxs[0] = worldorigin[0] + worldsize;
11110         worldmaxs[1] = worldorigin[1] + worldsize;
11111         worldmaxs[2] = worldorigin[2] + worldsize;
11112
11113         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11114
11115         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11116         {
11117                 ent = r_refdef.scene.entities[renderentityindex];
11118                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11119                         continue;
11120
11121                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11122         }
11123 }
11124
11125 typedef struct r_decalsystem_splatqueue_s
11126 {
11127         vec3_t worldorigin;
11128         vec3_t worldnormal;
11129         float color[4];
11130         float tcrange[4];
11131         float worldsize;
11132         int decalsequence;
11133 }
11134 r_decalsystem_splatqueue_t;
11135
11136 int r_decalsystem_numqueued = 0;
11137 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11138
11139 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)
11140 {
11141         r_decalsystem_splatqueue_t *queue;
11142
11143         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11144                 return;
11145
11146         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11147         VectorCopy(worldorigin, queue->worldorigin);
11148         VectorCopy(worldnormal, queue->worldnormal);
11149         Vector4Set(queue->color, r, g, b, a);
11150         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11151         queue->worldsize = worldsize;
11152         queue->decalsequence = cl.decalsequence++;
11153 }
11154
11155 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11156 {
11157         int i;
11158         r_decalsystem_splatqueue_t *queue;
11159
11160         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11161                 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);
11162         r_decalsystem_numqueued = 0;
11163 }
11164
11165 extern cvar_t cl_decals_max;
11166 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11167 {
11168         int i;
11169         decalsystem_t *decalsystem = &ent->decalsystem;
11170         int numdecals;
11171         int killsequence;
11172         tridecal_t *decal;
11173         float frametime;
11174         float lifetime;
11175
11176         if (!decalsystem->numdecals)
11177                 return;
11178
11179         if (r_showsurfaces.integer)
11180                 return;
11181
11182         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11183         {
11184                 R_DecalSystem_Reset(decalsystem);
11185                 return;
11186         }
11187
11188         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11189         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11190
11191         if (decalsystem->lastupdatetime)
11192                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11193         else
11194                 frametime = 0;
11195         decalsystem->lastupdatetime = r_refdef.scene.time;
11196         numdecals = decalsystem->numdecals;
11197
11198         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11199         {
11200                 if (decal->color4f[0][3])
11201                 {
11202                         decal->lived += frametime;
11203                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11204                         {
11205                                 memset(decal, 0, sizeof(*decal));
11206                                 if (decalsystem->freedecal > i)
11207                                         decalsystem->freedecal = i;
11208                         }
11209                 }
11210         }
11211         decal = decalsystem->decals;
11212         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11213                 numdecals--;
11214
11215         // collapse the array by shuffling the tail decals into the gaps
11216         for (;;)
11217         {
11218                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11219                         decalsystem->freedecal++;
11220                 if (decalsystem->freedecal == numdecals)
11221                         break;
11222                 decal[decalsystem->freedecal] = decal[--numdecals];
11223         }
11224
11225         decalsystem->numdecals = numdecals;
11226
11227         if (numdecals <= 0)
11228         {
11229                 // if there are no decals left, reset decalsystem
11230                 R_DecalSystem_Reset(decalsystem);
11231         }
11232 }
11233
11234 extern skinframe_t *decalskinframe;
11235 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11236 {
11237         int i;
11238         decalsystem_t *decalsystem = &ent->decalsystem;
11239         int numdecals;
11240         tridecal_t *decal;
11241         float faderate;
11242         float alpha;
11243         float *v3f;
11244         float *c4f;
11245         float *t2f;
11246         const int *e;
11247         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11248         int numtris = 0;
11249
11250         numdecals = decalsystem->numdecals;
11251         if (!numdecals)
11252                 return;
11253
11254         if (r_showsurfaces.integer)
11255                 return;
11256
11257         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11258         {
11259                 R_DecalSystem_Reset(decalsystem);
11260                 return;
11261         }
11262
11263         // if the model is static it doesn't matter what value we give for
11264         // wantnormals and wanttangents, so this logic uses only rules applicable
11265         // to a model, knowing that they are meaningless otherwise
11266         if (ent == r_refdef.scene.worldentity)
11267                 RSurf_ActiveWorldEntity();
11268         else
11269                 RSurf_ActiveModelEntity(ent, false, false, false);
11270
11271         decalsystem->lastupdatetime = r_refdef.scene.time;
11272
11273         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11274
11275         // update vertex positions for animated models
11276         v3f = decalsystem->vertex3f;
11277         c4f = decalsystem->color4f;
11278         t2f = decalsystem->texcoord2f;
11279         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11280         {
11281                 if (!decal->color4f[0][3])
11282                         continue;
11283
11284                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11285                         continue;
11286
11287                 // skip backfaces
11288                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11289                         continue;
11290
11291                 // update color values for fading decals
11292                 if (decal->lived >= cl_decals_time.value)
11293                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11294                 else
11295                         alpha = 1.0f;
11296
11297                 c4f[ 0] = decal->color4f[0][0] * alpha;
11298                 c4f[ 1] = decal->color4f[0][1] * alpha;
11299                 c4f[ 2] = decal->color4f[0][2] * alpha;
11300                 c4f[ 3] = 1;
11301                 c4f[ 4] = decal->color4f[1][0] * alpha;
11302                 c4f[ 5] = decal->color4f[1][1] * alpha;
11303                 c4f[ 6] = decal->color4f[1][2] * alpha;
11304                 c4f[ 7] = 1;
11305                 c4f[ 8] = decal->color4f[2][0] * alpha;
11306                 c4f[ 9] = decal->color4f[2][1] * alpha;
11307                 c4f[10] = decal->color4f[2][2] * alpha;
11308                 c4f[11] = 1;
11309
11310                 t2f[0] = decal->texcoord2f[0][0];
11311                 t2f[1] = decal->texcoord2f[0][1];
11312                 t2f[2] = decal->texcoord2f[1][0];
11313                 t2f[3] = decal->texcoord2f[1][1];
11314                 t2f[4] = decal->texcoord2f[2][0];
11315                 t2f[5] = decal->texcoord2f[2][1];
11316
11317                 // update vertex positions for animated models
11318                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11319                 {
11320                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11321                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11322                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11323                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11324                 }
11325                 else
11326                 {
11327                         VectorCopy(decal->vertex3f[0], v3f);
11328                         VectorCopy(decal->vertex3f[1], v3f + 3);
11329                         VectorCopy(decal->vertex3f[2], v3f + 6);
11330                 }
11331
11332                 if (r_refdef.fogenabled)
11333                 {
11334                         alpha = RSurf_FogVertex(v3f);
11335                         VectorScale(c4f, alpha, c4f);
11336                         alpha = RSurf_FogVertex(v3f + 3);
11337                         VectorScale(c4f + 4, alpha, c4f + 4);
11338                         alpha = RSurf_FogVertex(v3f + 6);
11339                         VectorScale(c4f + 8, alpha, c4f + 8);
11340                 }
11341
11342                 v3f += 9;
11343                 c4f += 12;
11344                 t2f += 6;
11345                 numtris++;
11346         }
11347
11348         if (numtris > 0)
11349         {
11350                 r_refdef.stats.drawndecals += numtris;
11351
11352                 // now render the decals all at once
11353                 // (this assumes they all use one particle font texture!)
11354                 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);
11355 //              R_Mesh_ResetTextureState();
11356                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11357                 GL_DepthMask(false);
11358                 GL_DepthRange(0, 1);
11359                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11360                 GL_DepthTest(true);
11361                 GL_CullFace(GL_NONE);
11362                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11363                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11364                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11365         }
11366 }
11367
11368 static void R_DrawModelDecals(void)
11369 {
11370         int i, numdecals;
11371
11372         // fade faster when there are too many decals
11373         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11374         for (i = 0;i < r_refdef.scene.numentities;i++)
11375                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11376
11377         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11378         for (i = 0;i < r_refdef.scene.numentities;i++)
11379                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11380                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11381
11382         R_DecalSystem_ApplySplatEntitiesQueue();
11383
11384         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11385         for (i = 0;i < r_refdef.scene.numentities;i++)
11386                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11387
11388         r_refdef.stats.totaldecals += numdecals;
11389
11390         if (r_showsurfaces.integer)
11391                 return;
11392
11393         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11394
11395         for (i = 0;i < r_refdef.scene.numentities;i++)
11396         {
11397                 if (!r_refdef.viewcache.entityvisible[i])
11398                         continue;
11399                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11400                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11401         }
11402 }
11403
11404 extern cvar_t mod_collision_bih;
11405 static void R_DrawDebugModel(void)
11406 {
11407         entity_render_t *ent = rsurface.entity;
11408         int i, j, k, l, flagsmask;
11409         const msurface_t *surface;
11410         dp_model_t *model = ent->model;
11411         vec3_t v;
11412
11413         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11414                 return;
11415
11416         if (r_showoverdraw.value > 0)
11417         {
11418                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11419                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11420                 R_SetupShader_Generic_NoTexture(false, false);
11421                 GL_DepthTest(false);
11422                 GL_DepthMask(false);
11423                 GL_DepthRange(0, 1);
11424                 GL_BlendFunc(GL_ONE, GL_ONE);
11425                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11426                 {
11427                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11428                                 continue;
11429                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11430                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11431                         {
11432                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11433                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11434                                 if (!rsurface.texture->currentlayers->depthmask)
11435                                         GL_Color(c, 0, 0, 1.0f);
11436                                 else if (ent == r_refdef.scene.worldentity)
11437                                         GL_Color(c, c, c, 1.0f);
11438                                 else
11439                                         GL_Color(0, c, 0, 1.0f);
11440                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11441                                 RSurf_DrawBatch();
11442                         }
11443                 }
11444                 rsurface.texture = NULL;
11445         }
11446
11447         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11448
11449 //      R_Mesh_ResetTextureState();
11450         R_SetupShader_Generic_NoTexture(false, false);
11451         GL_DepthRange(0, 1);
11452         GL_DepthTest(!r_showdisabledepthtest.integer);
11453         GL_DepthMask(false);
11454         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11455
11456         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11457         {
11458                 int triangleindex;
11459                 int bihleafindex;
11460                 qboolean cullbox = false;
11461                 const q3mbrush_t *brush;
11462                 const bih_t *bih = &model->collision_bih;
11463                 const bih_leaf_t *bihleaf;
11464                 float vertex3f[3][3];
11465                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11466                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11467                 {
11468                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11469                                 continue;
11470                         switch (bihleaf->type)
11471                         {
11472                         case BIH_BRUSH:
11473                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11474                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11475                                 {
11476                                         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);
11477                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11478                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11479                                 }
11480                                 break;
11481                         case BIH_COLLISIONTRIANGLE:
11482                                 triangleindex = bihleaf->itemindex;
11483                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11484                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11485                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11486                                 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);
11487                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11488                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11489                                 break;
11490                         case BIH_RENDERTRIANGLE:
11491                                 triangleindex = bihleaf->itemindex;
11492                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11493                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11494                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11495                                 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);
11496                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11497                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11498                                 break;
11499                         }
11500                 }
11501         }
11502
11503         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11504
11505 #ifndef USE_GLES2
11506         if (r_showtris.integer && qglPolygonMode)
11507         {
11508                 if (r_showdisabledepthtest.integer)
11509                 {
11510                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11511                         GL_DepthMask(false);
11512                 }
11513                 else
11514                 {
11515                         GL_BlendFunc(GL_ONE, GL_ZERO);
11516                         GL_DepthMask(true);
11517                 }
11518                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11519                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11520                 {
11521                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11522                                 continue;
11523                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11524                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11525                         {
11526                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11527                                 if (!rsurface.texture->currentlayers->depthmask)
11528                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11529                                 else if (ent == r_refdef.scene.worldentity)
11530                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11531                                 else
11532                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11533                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11534                                 RSurf_DrawBatch();
11535                         }
11536                 }
11537                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11538                 rsurface.texture = NULL;
11539         }
11540
11541         if (r_shownormals.value != 0 && qglBegin)
11542         {
11543                 if (r_showdisabledepthtest.integer)
11544                 {
11545                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11546                         GL_DepthMask(false);
11547                 }
11548                 else
11549                 {
11550                         GL_BlendFunc(GL_ONE, GL_ZERO);
11551                         GL_DepthMask(true);
11552                 }
11553                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11554                 {
11555                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11556                                 continue;
11557                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11558                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11559                         {
11560                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11561                                 qglBegin(GL_LINES);
11562                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11563                                 {
11564                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11565                                         {
11566                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11567                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11568                                                 qglVertex3f(v[0], v[1], v[2]);
11569                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11570                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11571                                                 qglVertex3f(v[0], v[1], v[2]);
11572                                         }
11573                                 }
11574                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11575                                 {
11576                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11577                                         {
11578                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11579                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11580                                                 qglVertex3f(v[0], v[1], v[2]);
11581                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11582                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11583                                                 qglVertex3f(v[0], v[1], v[2]);
11584                                         }
11585                                 }
11586                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11587                                 {
11588                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11589                                         {
11590                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11591                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11592                                                 qglVertex3f(v[0], v[1], v[2]);
11593                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11594                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11595                                                 qglVertex3f(v[0], v[1], v[2]);
11596                                         }
11597                                 }
11598                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11599                                 {
11600                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11601                                         {
11602                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11603                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11604                                                 qglVertex3f(v[0], v[1], v[2]);
11605                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11606                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11607                                                 qglVertex3f(v[0], v[1], v[2]);
11608                                         }
11609                                 }
11610                                 qglEnd();
11611                                 CHECKGLERROR
11612                         }
11613                 }
11614                 rsurface.texture = NULL;
11615         }
11616 #endif
11617 }
11618
11619 int r_maxsurfacelist = 0;
11620 const msurface_t **r_surfacelist = NULL;
11621 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11622 {
11623         int i, j, endj, flagsmask;
11624         dp_model_t *model = r_refdef.scene.worldmodel;
11625         msurface_t *surfaces;
11626         unsigned char *update;
11627         int numsurfacelist = 0;
11628         if (model == NULL)
11629                 return;
11630
11631         if (r_maxsurfacelist < model->num_surfaces)
11632         {
11633                 r_maxsurfacelist = model->num_surfaces;
11634                 if (r_surfacelist)
11635                         Mem_Free((msurface_t**)r_surfacelist);
11636                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11637         }
11638
11639         RSurf_ActiveWorldEntity();
11640
11641         surfaces = model->data_surfaces;
11642         update = model->brushq1.lightmapupdateflags;
11643
11644         // update light styles on this submodel
11645         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11646         {
11647                 model_brush_lightstyleinfo_t *style;
11648                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11649                 {
11650                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11651                         {
11652                                 int *list = style->surfacelist;
11653                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11654                                 for (j = 0;j < style->numsurfaces;j++)
11655                                         update[list[j]] = true;
11656                         }
11657                 }
11658         }
11659
11660         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11661
11662         if (debug)
11663         {
11664                 R_DrawDebugModel();
11665                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11666                 return;
11667         }
11668
11669         rsurface.lightmaptexture = NULL;
11670         rsurface.deluxemaptexture = NULL;
11671         rsurface.uselightmaptexture = false;
11672         rsurface.texture = NULL;
11673         rsurface.rtlight = NULL;
11674         numsurfacelist = 0;
11675         // add visible surfaces to draw list
11676         for (i = 0;i < model->nummodelsurfaces;i++)
11677         {
11678                 j = model->sortedmodelsurfaces[i];
11679                 if (r_refdef.viewcache.world_surfacevisible[j])
11680                         r_surfacelist[numsurfacelist++] = surfaces + j;
11681         }
11682         // update lightmaps if needed
11683         if (model->brushq1.firstrender)
11684         {
11685                 model->brushq1.firstrender = false;
11686                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11687                         if (update[j])
11688                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11689         }
11690         else if (update)
11691         {
11692                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11693                         if (r_refdef.viewcache.world_surfacevisible[j])
11694                                 if (update[j])
11695                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11696         }
11697         // don't do anything if there were no surfaces
11698         if (!numsurfacelist)
11699         {
11700                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11701                 return;
11702         }
11703         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11704
11705         // add to stats if desired
11706         if (r_speeds.integer && !skysurfaces && !depthonly)
11707         {
11708                 r_refdef.stats.world_surfaces += numsurfacelist;
11709                 for (j = 0;j < numsurfacelist;j++)
11710                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11711         }
11712
11713         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11714 }
11715
11716 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11717 {
11718         int i, j, endj, flagsmask;
11719         dp_model_t *model = ent->model;
11720         msurface_t *surfaces;
11721         unsigned char *update;
11722         int numsurfacelist = 0;
11723         if (model == NULL)
11724                 return;
11725
11726         if (r_maxsurfacelist < model->num_surfaces)
11727         {
11728                 r_maxsurfacelist = model->num_surfaces;
11729                 if (r_surfacelist)
11730                         Mem_Free((msurface_t **)r_surfacelist);
11731                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11732         }
11733
11734         // if the model is static it doesn't matter what value we give for
11735         // wantnormals and wanttangents, so this logic uses only rules applicable
11736         // to a model, knowing that they are meaningless otherwise
11737         if (ent == r_refdef.scene.worldentity)
11738                 RSurf_ActiveWorldEntity();
11739         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11740                 RSurf_ActiveModelEntity(ent, false, false, false);
11741         else if (prepass)
11742                 RSurf_ActiveModelEntity(ent, true, true, true);
11743         else if (depthonly)
11744         {
11745                 switch (vid.renderpath)
11746                 {
11747                 case RENDERPATH_GL20:
11748                 case RENDERPATH_D3D9:
11749                 case RENDERPATH_D3D10:
11750                 case RENDERPATH_D3D11:
11751                 case RENDERPATH_SOFT:
11752                 case RENDERPATH_GLES2:
11753                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11754                         break;
11755                 case RENDERPATH_GL11:
11756                 case RENDERPATH_GL13:
11757                 case RENDERPATH_GLES1:
11758                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11759                         break;
11760                 }
11761         }
11762         else
11763         {
11764                 switch (vid.renderpath)
11765                 {
11766                 case RENDERPATH_GL20:
11767                 case RENDERPATH_D3D9:
11768                 case RENDERPATH_D3D10:
11769                 case RENDERPATH_D3D11:
11770                 case RENDERPATH_SOFT:
11771                 case RENDERPATH_GLES2:
11772                         RSurf_ActiveModelEntity(ent, true, true, false);
11773                         break;
11774                 case RENDERPATH_GL11:
11775                 case RENDERPATH_GL13:
11776                 case RENDERPATH_GLES1:
11777                         RSurf_ActiveModelEntity(ent, true, false, false);
11778                         break;
11779                 }
11780         }
11781
11782         surfaces = model->data_surfaces;
11783         update = model->brushq1.lightmapupdateflags;
11784
11785         // update light styles
11786         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11787         {
11788                 model_brush_lightstyleinfo_t *style;
11789                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11790                 {
11791                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11792                         {
11793                                 int *list = style->surfacelist;
11794                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11795                                 for (j = 0;j < style->numsurfaces;j++)
11796                                         update[list[j]] = true;
11797                         }
11798                 }
11799         }
11800
11801         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11802
11803         if (debug)
11804         {
11805                 R_DrawDebugModel();
11806                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11807                 return;
11808         }
11809
11810         rsurface.lightmaptexture = NULL;
11811         rsurface.deluxemaptexture = NULL;
11812         rsurface.uselightmaptexture = false;
11813         rsurface.texture = NULL;
11814         rsurface.rtlight = NULL;
11815         numsurfacelist = 0;
11816         // add visible surfaces to draw list
11817         for (i = 0;i < model->nummodelsurfaces;i++)
11818                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11819         // don't do anything if there were no surfaces
11820         if (!numsurfacelist)
11821         {
11822                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11823                 return;
11824         }
11825         // update lightmaps if needed
11826         if (update)
11827         {
11828                 int updated = 0;
11829                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11830                 {
11831                         if (update[j])
11832                         {
11833                                 updated++;
11834                                 R_BuildLightMap(ent, surfaces + j);
11835                         }
11836                 }
11837         }
11838
11839         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11840
11841         // add to stats if desired
11842         if (r_speeds.integer && !skysurfaces && !depthonly)
11843         {
11844                 r_refdef.stats.entities_surfaces += numsurfacelist;
11845                 for (j = 0;j < numsurfacelist;j++)
11846                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11847         }
11848
11849         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11850 }
11851
11852 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11853 {
11854         static texture_t texture;
11855         static msurface_t surface;
11856         const msurface_t *surfacelist = &surface;
11857
11858         // fake enough texture and surface state to render this geometry
11859
11860         texture.update_lastrenderframe = -1; // regenerate this texture
11861         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11862         texture.currentskinframe = skinframe;
11863         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11864         texture.offsetmapping = OFFSETMAPPING_OFF;
11865         texture.offsetscale = 1;
11866         texture.specularscalemod = 1;
11867         texture.specularpowermod = 1;
11868
11869         surface.texture = &texture;
11870         surface.num_triangles = numtriangles;
11871         surface.num_firsttriangle = firsttriangle;
11872         surface.num_vertices = numvertices;
11873         surface.num_firstvertex = firstvertex;
11874
11875         // now render it
11876         rsurface.texture = R_GetCurrentTexture(surface.texture);
11877         rsurface.lightmaptexture = NULL;
11878         rsurface.deluxemaptexture = NULL;
11879         rsurface.uselightmaptexture = false;
11880         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11881 }
11882
11883 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)
11884 {
11885         static msurface_t surface;
11886         const msurface_t *surfacelist = &surface;
11887
11888         // fake enough texture and surface state to render this geometry
11889         surface.texture = texture;
11890         surface.num_triangles = numtriangles;
11891         surface.num_firsttriangle = firsttriangle;
11892         surface.num_vertices = numvertices;
11893         surface.num_firstvertex = firstvertex;
11894
11895         // now render it
11896         rsurface.texture = R_GetCurrentTexture(surface.texture);
11897         rsurface.lightmaptexture = NULL;
11898         rsurface.deluxemaptexture = NULL;
11899         rsurface.uselightmaptexture = false;
11900         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11901 }