]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
fix for .alpha and other effects on sprites that use the same frame,
[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"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
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"};
136 cvar_t r_celoutlines = {CVAR_SAVE, "r_celoutlines", "0", "cartoon-style outlines (requires r_shadow_deferred)"};
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
207 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
208 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
209 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
210 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
211 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
212 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
213 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
214 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
215 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
216 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
217
218 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"};
219
220 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"};
221
222 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
223
224 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
225
226 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
227 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"};
228
229 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."};
230
231 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)"};
232
233 extern cvar_t v_glslgamma;
234 extern cvar_t v_glslgamma_2d;
235
236 extern qboolean v_flipped_state;
237
238 r_framebufferstate_t r_fb;
239
240 /// shadow volume bsp struct with automatically growing nodes buffer
241 svbsp_t r_svbsp;
242
243 rtexture_t *r_texture_blanknormalmap;
244 rtexture_t *r_texture_white;
245 rtexture_t *r_texture_grey128;
246 rtexture_t *r_texture_black;
247 rtexture_t *r_texture_notexture;
248 rtexture_t *r_texture_whitecube;
249 rtexture_t *r_texture_normalizationcube;
250 rtexture_t *r_texture_fogattenuation;
251 rtexture_t *r_texture_fogheighttexture;
252 rtexture_t *r_texture_gammaramps;
253 unsigned int r_texture_gammaramps_serial;
254 //rtexture_t *r_texture_fogintensity;
255 rtexture_t *r_texture_reflectcube;
256
257 // TODO: hash lookups?
258 typedef struct cubemapinfo_s
259 {
260         char basename[64];
261         rtexture_t *texture;
262 }
263 cubemapinfo_t;
264
265 int r_texture_numcubemaps;
266 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
267
268 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
269 unsigned int r_numqueries;
270 unsigned int r_maxqueries;
271
272 typedef struct r_qwskincache_s
273 {
274         char name[MAX_QPATH];
275         skinframe_t *skinframe;
276 }
277 r_qwskincache_t;
278
279 static r_qwskincache_t *r_qwskincache;
280 static int r_qwskincache_size;
281
282 /// vertex coordinates for a quad that covers the screen exactly
283 extern const float r_screenvertex3f[12];
284 extern const float r_d3dscreenvertex3f[12];
285 const float r_screenvertex3f[12] =
286 {
287         0, 0, 0,
288         1, 0, 0,
289         1, 1, 0,
290         0, 1, 0
291 };
292 const float r_d3dscreenvertex3f[12] =
293 {
294         0, 1, 0,
295         1, 1, 0,
296         1, 0, 0,
297         0, 0, 0
298 };
299
300 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
301 {
302         int i;
303         for (i = 0;i < verts;i++)
304         {
305                 out[0] = in[0] * r;
306                 out[1] = in[1] * g;
307                 out[2] = in[2] * b;
308                 out[3] = in[3];
309                 in += 4;
310                 out += 4;
311         }
312 }
313
314 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
315 {
316         int i;
317         for (i = 0;i < verts;i++)
318         {
319                 out[0] = r;
320                 out[1] = g;
321                 out[2] = b;
322                 out[3] = a;
323                 out += 4;
324         }
325 }
326
327 // FIXME: move this to client?
328 void FOG_clear(void)
329 {
330         if (gamemode == GAME_NEHAHRA)
331         {
332                 Cvar_Set("gl_fogenable", "0");
333                 Cvar_Set("gl_fogdensity", "0.2");
334                 Cvar_Set("gl_fogred", "0.3");
335                 Cvar_Set("gl_foggreen", "0.3");
336                 Cvar_Set("gl_fogblue", "0.3");
337         }
338         r_refdef.fog_density = 0;
339         r_refdef.fog_red = 0;
340         r_refdef.fog_green = 0;
341         r_refdef.fog_blue = 0;
342         r_refdef.fog_alpha = 1;
343         r_refdef.fog_start = 0;
344         r_refdef.fog_end = 16384;
345         r_refdef.fog_height = 1<<30;
346         r_refdef.fog_fadedepth = 128;
347         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
348 }
349
350 static void R_BuildBlankTextures(void)
351 {
352         unsigned char data[4];
353         data[2] = 128; // normal X
354         data[1] = 128; // normal Y
355         data[0] = 255; // normal Z
356         data[3] = 255; // height
357         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
358         data[0] = 255;
359         data[1] = 255;
360         data[2] = 255;
361         data[3] = 255;
362         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
363         data[0] = 128;
364         data[1] = 128;
365         data[2] = 128;
366         data[3] = 255;
367         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
368         data[0] = 0;
369         data[1] = 0;
370         data[2] = 0;
371         data[3] = 255;
372         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
373 }
374
375 static void R_BuildNoTexture(void)
376 {
377         int x, y;
378         unsigned char pix[16][16][4];
379         // this makes a light grey/dark grey checkerboard texture
380         for (y = 0;y < 16;y++)
381         {
382                 for (x = 0;x < 16;x++)
383                 {
384                         if ((y < 8) ^ (x < 8))
385                         {
386                                 pix[y][x][0] = 128;
387                                 pix[y][x][1] = 128;
388                                 pix[y][x][2] = 128;
389                                 pix[y][x][3] = 255;
390                         }
391                         else
392                         {
393                                 pix[y][x][0] = 64;
394                                 pix[y][x][1] = 64;
395                                 pix[y][x][2] = 64;
396                                 pix[y][x][3] = 255;
397                         }
398                 }
399         }
400         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
401 }
402
403 static void R_BuildWhiteCube(void)
404 {
405         unsigned char data[6*1*1*4];
406         memset(data, 255, sizeof(data));
407         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
408 }
409
410 static void R_BuildNormalizationCube(void)
411 {
412         int x, y, side;
413         vec3_t v;
414         vec_t s, t, intensity;
415 #define NORMSIZE 64
416         unsigned char *data;
417         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
418         for (side = 0;side < 6;side++)
419         {
420                 for (y = 0;y < NORMSIZE;y++)
421                 {
422                         for (x = 0;x < NORMSIZE;x++)
423                         {
424                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
425                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
426                                 switch(side)
427                                 {
428                                 default:
429                                 case 0:
430                                         v[0] = 1;
431                                         v[1] = -t;
432                                         v[2] = -s;
433                                         break;
434                                 case 1:
435                                         v[0] = -1;
436                                         v[1] = -t;
437                                         v[2] = s;
438                                         break;
439                                 case 2:
440                                         v[0] = s;
441                                         v[1] = 1;
442                                         v[2] = t;
443                                         break;
444                                 case 3:
445                                         v[0] = s;
446                                         v[1] = -1;
447                                         v[2] = -t;
448                                         break;
449                                 case 4:
450                                         v[0] = s;
451                                         v[1] = -t;
452                                         v[2] = 1;
453                                         break;
454                                 case 5:
455                                         v[0] = -s;
456                                         v[1] = -t;
457                                         v[2] = -1;
458                                         break;
459                                 }
460                                 intensity = 127.0f / sqrt(DotProduct(v, v));
461                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
462                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
463                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
464                                 data[((side*64+y)*64+x)*4+3] = 255;
465                         }
466                 }
467         }
468         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
469         Mem_Free(data);
470 }
471
472 static void R_BuildFogTexture(void)
473 {
474         int x, b;
475 #define FOGWIDTH 256
476         unsigned char data1[FOGWIDTH][4];
477         //unsigned char data2[FOGWIDTH][4];
478         double d, r, alpha;
479
480         r_refdef.fogmasktable_start = r_refdef.fog_start;
481         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
482         r_refdef.fogmasktable_range = r_refdef.fogrange;
483         r_refdef.fogmasktable_density = r_refdef.fog_density;
484
485         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
486         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
487         {
488                 d = (x * r - r_refdef.fogmasktable_start);
489                 if(developer_extra.integer)
490                         Con_DPrintf("%f ", d);
491                 d = max(0, d);
492                 if (r_fog_exp2.integer)
493                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
494                 else
495                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
496                 if(developer_extra.integer)
497                         Con_DPrintf(" : %f ", alpha);
498                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
499                 if(developer_extra.integer)
500                         Con_DPrintf(" = %f\n", alpha);
501                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
502         }
503
504         for (x = 0;x < FOGWIDTH;x++)
505         {
506                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
507                 data1[x][0] = b;
508                 data1[x][1] = b;
509                 data1[x][2] = b;
510                 data1[x][3] = 255;
511                 //data2[x][0] = 255 - b;
512                 //data2[x][1] = 255 - b;
513                 //data2[x][2] = 255 - b;
514                 //data2[x][3] = 255;
515         }
516         if (r_texture_fogattenuation)
517         {
518                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
519                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
520         }
521         else
522         {
523                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
524                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
525         }
526 }
527
528 static void R_BuildFogHeightTexture(void)
529 {
530         unsigned char *inpixels;
531         int size;
532         int x;
533         int y;
534         int j;
535         float c[4];
536         float f;
537         inpixels = NULL;
538         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
539         if (r_refdef.fogheighttexturename[0])
540                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
541         if (!inpixels)
542         {
543                 r_refdef.fog_height_tablesize = 0;
544                 if (r_texture_fogheighttexture)
545                         R_FreeTexture(r_texture_fogheighttexture);
546                 r_texture_fogheighttexture = NULL;
547                 if (r_refdef.fog_height_table2d)
548                         Mem_Free(r_refdef.fog_height_table2d);
549                 r_refdef.fog_height_table2d = NULL;
550                 if (r_refdef.fog_height_table1d)
551                         Mem_Free(r_refdef.fog_height_table1d);
552                 r_refdef.fog_height_table1d = NULL;
553                 return;
554         }
555         size = image_width;
556         r_refdef.fog_height_tablesize = size;
557         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
558         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
559         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
560         Mem_Free(inpixels);
561         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
562         // average fog color table accounting for every fog layer between a point
563         // and the camera.  (Note: attenuation is handled separately!)
564         for (y = 0;y < size;y++)
565         {
566                 for (x = 0;x < size;x++)
567                 {
568                         Vector4Clear(c);
569                         f = 0;
570                         if (x < y)
571                         {
572                                 for (j = x;j <= y;j++)
573                                 {
574                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
575                                         f++;
576                                 }
577                         }
578                         else
579                         {
580                                 for (j = x;j >= y;j--)
581                                 {
582                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
583                                         f++;
584                                 }
585                         }
586                         f = 1.0f / f;
587                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
588                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
589                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
590                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
591                 }
592         }
593         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
594 }
595
596 //=======================================================================================================================================================
597
598 static const char *builtinshaderstring =
599 #include "shader_glsl.h"
600 ;
601
602 const char *builtinhlslshaderstring =
603 #include "shader_hlsl.h"
604 ;
605
606 char *glslshaderstring = NULL;
607 char *hlslshaderstring = NULL;
608
609 //=======================================================================================================================================================
610
611 typedef struct shaderpermutationinfo_s
612 {
613         const char *pretext;
614         const char *name;
615 }
616 shaderpermutationinfo_t;
617
618 typedef struct shadermodeinfo_s
619 {
620         const char *vertexfilename;
621         const char *geometryfilename;
622         const char *fragmentfilename;
623         const char *pretext;
624         const char *name;
625 }
626 shadermodeinfo_t;
627
628 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
629 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
630 {
631         {"#define USEDIFFUSE\n", " diffuse"},
632         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
633         {"#define USEVIEWTINT\n", " viewtint"},
634         {"#define USECOLORMAPPING\n", " colormapping"},
635         {"#define USESATURATION\n", " saturation"},
636         {"#define USEFOGINSIDE\n", " foginside"},
637         {"#define USEFOGOUTSIDE\n", " fogoutside"},
638         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
639         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
640         {"#define USEGAMMARAMPS\n", " gammaramps"},
641         {"#define USECUBEFILTER\n", " cubefilter"},
642         {"#define USEGLOW\n", " glow"},
643         {"#define USEBLOOM\n", " bloom"},
644         {"#define USESPECULAR\n", " specular"},
645         {"#define USEPOSTPROCESSING\n", " postprocessing"},
646         {"#define USEREFLECTION\n", " reflection"},
647         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
648         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
649         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
650         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
651         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
652         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
653         {"#define USEALPHAKILL\n", " alphakill"},
654         {"#define USEREFLECTCUBE\n", " reflectcube"},
655         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
656         {"#define USEBOUNCEGRID\n", " bouncegrid"},
657         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
658         {"#define USETRIPPY\n", " trippy"},
659         {"#define USEDEPTHRGB\n", " depthrgb"},
660         {"#define USEALPHAGENVERTEX\n", "alphagenvertex"}
661 };
662
663 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
664 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
665 {
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
682         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
683         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
684 };
685
686 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
687 {
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
704         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
705         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
706 };
707
708 struct r_glsl_permutation_s;
709 typedef struct r_glsl_permutation_s
710 {
711         /// hash lookup data
712         struct r_glsl_permutation_s *hashnext;
713         unsigned int mode;
714         unsigned int permutation;
715
716         /// indicates if we have tried compiling this permutation already
717         qboolean compiled;
718         /// 0 if compilation failed
719         int program;
720         // texture units assigned to each detected uniform
721         int tex_Texture_First;
722         int tex_Texture_Second;
723         int tex_Texture_GammaRamps;
724         int tex_Texture_Normal;
725         int tex_Texture_Color;
726         int tex_Texture_Gloss;
727         int tex_Texture_Glow;
728         int tex_Texture_SecondaryNormal;
729         int tex_Texture_SecondaryColor;
730         int tex_Texture_SecondaryGloss;
731         int tex_Texture_SecondaryGlow;
732         int tex_Texture_Pants;
733         int tex_Texture_Shirt;
734         int tex_Texture_FogHeightTexture;
735         int tex_Texture_FogMask;
736         int tex_Texture_Lightmap;
737         int tex_Texture_Deluxemap;
738         int tex_Texture_Attenuation;
739         int tex_Texture_Cube;
740         int tex_Texture_Refraction;
741         int tex_Texture_Reflection;
742         int tex_Texture_ShadowMap2D;
743         int tex_Texture_CubeProjection;
744         int tex_Texture_ScreenNormalMap;
745         int tex_Texture_ScreenDiffuse;
746         int tex_Texture_ScreenSpecular;
747         int tex_Texture_ReflectMask;
748         int tex_Texture_ReflectCube;
749         int tex_Texture_BounceGrid;
750         /// locations of detected uniforms in program object, or -1 if not found
751         int loc_Texture_First;
752         int loc_Texture_Second;
753         int loc_Texture_GammaRamps;
754         int loc_Texture_Normal;
755         int loc_Texture_Color;
756         int loc_Texture_Gloss;
757         int loc_Texture_Glow;
758         int loc_Texture_SecondaryNormal;
759         int loc_Texture_SecondaryColor;
760         int loc_Texture_SecondaryGloss;
761         int loc_Texture_SecondaryGlow;
762         int loc_Texture_Pants;
763         int loc_Texture_Shirt;
764         int loc_Texture_FogHeightTexture;
765         int loc_Texture_FogMask;
766         int loc_Texture_Lightmap;
767         int loc_Texture_Deluxemap;
768         int loc_Texture_Attenuation;
769         int loc_Texture_Cube;
770         int loc_Texture_Refraction;
771         int loc_Texture_Reflection;
772         int loc_Texture_ShadowMap2D;
773         int loc_Texture_CubeProjection;
774         int loc_Texture_ScreenNormalMap;
775         int loc_Texture_ScreenDiffuse;
776         int loc_Texture_ScreenSpecular;
777         int loc_Texture_ReflectMask;
778         int loc_Texture_ReflectCube;
779         int loc_Texture_BounceGrid;
780         int loc_Alpha;
781         int loc_BloomBlur_Parameters;
782         int loc_ClientTime;
783         int loc_Color_Ambient;
784         int loc_Color_Diffuse;
785         int loc_Color_Specular;
786         int loc_Color_Glow;
787         int loc_Color_Pants;
788         int loc_Color_Shirt;
789         int loc_DeferredColor_Ambient;
790         int loc_DeferredColor_Diffuse;
791         int loc_DeferredColor_Specular;
792         int loc_DeferredMod_Diffuse;
793         int loc_DeferredMod_Specular;
794         int loc_DistortScaleRefractReflect;
795         int loc_EyePosition;
796         int loc_FogColor;
797         int loc_FogHeightFade;
798         int loc_FogPlane;
799         int loc_FogPlaneViewDist;
800         int loc_FogRangeRecip;
801         int loc_LightColor;
802         int loc_LightDir;
803         int loc_LightPosition;
804         int loc_OffsetMapping_ScaleSteps;
805         int loc_OffsetMapping_LodDistance;
806         int loc_OffsetMapping_Bias;
807         int loc_PixelSize;
808         int loc_ReflectColor;
809         int loc_ReflectFactor;
810         int loc_ReflectOffset;
811         int loc_RefractColor;
812         int loc_Saturation;
813         int loc_ScreenCenterRefractReflect;
814         int loc_ScreenScaleRefractReflect;
815         int loc_ScreenToDepth;
816         int loc_ShadowMap_Parameters;
817         int loc_ShadowMap_TextureScale;
818         int loc_SpecularPower;
819         int loc_UserVec1;
820         int loc_UserVec2;
821         int loc_UserVec3;
822         int loc_UserVec4;
823         int loc_ViewTintColor;
824         int loc_ViewToLight;
825         int loc_ModelToLight;
826         int loc_TexMatrix;
827         int loc_BackgroundTexMatrix;
828         int loc_ModelViewProjectionMatrix;
829         int loc_ModelViewMatrix;
830         int loc_PixelToScreenTexCoord;
831         int loc_ModelToReflectCube;
832         int loc_ShadowMapMatrix;
833         int loc_BloomColorSubtract;
834         int loc_NormalmapScrollBlend;
835         int loc_BounceGridMatrix;
836         int loc_BounceGridIntensity;
837 }
838 r_glsl_permutation_t;
839
840 #define SHADERPERMUTATION_HASHSIZE 256
841
842
843 // non-degradable "lightweight" shader parameters to keep the permutations simpler
844 // these can NOT degrade! only use for simple stuff
845 enum
846 {
847         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
848         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
849         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
850         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
851         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
852         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
853         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
854         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
855         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
856         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
857         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
858         SHADERSTATICPARM_CELSHADING = 11, ///< celshading (alternative diffuse and specular math)
859         SHADERSTATICPARM_CELOUTLINES = 12, ///< celoutline (depth buffer analysis to produce outlines)
860 };
861 #define SHADERSTATICPARMS_COUNT 13
862
863 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
864 static int shaderstaticparms_count = 0;
865
866 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
867 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
868
869 extern qboolean r_shadow_shadowmapsampler;
870 extern int r_shadow_shadowmappcf;
871 qboolean R_CompileShader_CheckStaticParms(void)
872 {
873         static int r_compileshader_staticparms_save[1];
874         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
875         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
876
877         // detect all
878         if (r_glsl_saturation_redcompensate.integer)
879                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
880         if (r_glsl_vertextextureblend_usebothalphas.integer)
881                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
882         if (r_shadow_glossexact.integer)
883                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
884         if (r_glsl_postprocess.integer)
885         {
886                 if (r_glsl_postprocess_uservec1_enable.integer)
887                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
888                 if (r_glsl_postprocess_uservec2_enable.integer)
889                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
890                 if (r_glsl_postprocess_uservec3_enable.integer)
891                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
892                 if (r_glsl_postprocess_uservec4_enable.integer)
893                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
894         }
895         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
896                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
897
898         if (r_shadow_shadowmapsampler)
899                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
900         if (r_shadow_shadowmappcf > 1)
901                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
902         else if (r_shadow_shadowmappcf)
903                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
904         if (r_celshading.integer)
905                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELSHADING);
906         if (r_celoutlines.integer)
907                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_CELOUTLINES);
908
909         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
910 }
911
912 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
913         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
914                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
915         else \
916                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
917 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
918 {
919         shaderstaticparms_count = 0;
920
921         // emit all
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
925         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
926         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
927         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
928         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
929         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
930         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
931         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
932         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
933         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELSHADING, "USECELSHADING");
934         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_CELOUTLINES, "USECELOUTLINES");
935 }
936
937 /// information about each possible shader permutation
938 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
939 /// currently selected permutation
940 r_glsl_permutation_t *r_glsl_permutation;
941 /// storage for permutations linked in the hash table
942 memexpandablearray_t r_glsl_permutationarray;
943
944 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
945 {
946         //unsigned int hashdepth = 0;
947         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
948         r_glsl_permutation_t *p;
949         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
950         {
951                 if (p->mode == mode && p->permutation == permutation)
952                 {
953                         //if (hashdepth > 10)
954                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
955                         return p;
956                 }
957                 //hashdepth++;
958         }
959         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
960         p->mode = mode;
961         p->permutation = permutation;
962         p->hashnext = r_glsl_permutationhash[mode][hashindex];
963         r_glsl_permutationhash[mode][hashindex] = p;
964         //if (hashdepth > 10)
965         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
966         return p;
967 }
968
969 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
970 {
971         char *shaderstring;
972         if (!filename || !filename[0])
973                 return NULL;
974         if (!strcmp(filename, "glsl/default.glsl"))
975         {
976                 if (!glslshaderstring)
977                 {
978                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
979                         if (glslshaderstring)
980                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
981                         else
982                                 glslshaderstring = (char *)builtinshaderstring;
983                 }
984                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
985                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
986                 return shaderstring;
987         }
988         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
989         if (shaderstring)
990         {
991                 if (printfromdisknotice)
992                         Con_DPrintf("from disk %s... ", filename);
993                 return shaderstring;
994         }
995         return shaderstring;
996 }
997
998 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
999 {
1000         int i;
1001         int sampler;
1002         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
1003         char *vertexstring, *geometrystring, *fragmentstring;
1004         char permutationname[256];
1005         int vertstrings_count = 0;
1006         int geomstrings_count = 0;
1007         int fragstrings_count = 0;
1008         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1009         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1010         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1011
1012         if (p->compiled)
1013                 return;
1014         p->compiled = true;
1015         p->program = 0;
1016
1017         permutationname[0] = 0;
1018         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1019         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1020         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1021
1022         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1023
1024         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1025         if(vid.support.gl20shaders130)
1026         {
1027                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1028                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1029                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1030                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1031                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1032                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1033         }
1034
1035         // the first pretext is which type of shader to compile as
1036         // (later these will all be bound together as a program object)
1037         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1038         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1039         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1040
1041         // the second pretext is the mode (for example a light source)
1042         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1043         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1044         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1045         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1046
1047         // now add all the permutation pretexts
1048         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1049         {
1050                 if (permutation & (1<<i))
1051                 {
1052                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1053                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1054                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1055                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1056                 }
1057                 else
1058                 {
1059                         // keep line numbers correct
1060                         vertstrings_list[vertstrings_count++] = "\n";
1061                         geomstrings_list[geomstrings_count++] = "\n";
1062                         fragstrings_list[fragstrings_count++] = "\n";
1063                 }
1064         }
1065
1066         // add static parms
1067         R_CompileShader_AddStaticParms(mode, permutation);
1068         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1069         vertstrings_count += shaderstaticparms_count;
1070         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1071         geomstrings_count += shaderstaticparms_count;
1072         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1073         fragstrings_count += shaderstaticparms_count;
1074
1075         // now append the shader text itself
1076         vertstrings_list[vertstrings_count++] = vertexstring;
1077         geomstrings_list[geomstrings_count++] = geometrystring;
1078         fragstrings_list[fragstrings_count++] = fragmentstring;
1079
1080         // if any sources were NULL, clear the respective list
1081         if (!vertexstring)
1082                 vertstrings_count = 0;
1083         if (!geometrystring)
1084                 geomstrings_count = 0;
1085         if (!fragmentstring)
1086                 fragstrings_count = 0;
1087
1088         // compile the shader program
1089         if (vertstrings_count + geomstrings_count + fragstrings_count)
1090                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1091         if (p->program)
1092         {
1093                 CHECKGLERROR
1094                 qglUseProgram(p->program);CHECKGLERROR
1095                 // look up all the uniform variable names we care about, so we don't
1096                 // have to look them up every time we set them
1097
1098                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1099                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1100                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1101                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1102                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1103                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1104                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1105                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1106                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1107                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1108                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1109                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1110                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1111                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1112                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1113                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1114                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1115                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1116                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1117                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1118                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1119                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1120                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1121                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1122                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1123                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1124                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1125                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1126                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1127                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1128                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1129                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1130                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1131                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1132                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1133                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1134                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1135                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1136                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1137                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1138                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1139                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1140                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1141                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1142                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1143                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1144                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1145                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1146                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1147                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1148                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1149                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1150                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1151                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1152                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1153                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1154                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1155                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1156                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1157                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1158                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1159                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1160                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1161                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1162                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1163                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1164                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1165                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1166                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1167                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1168                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1169                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1170                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1171                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1172                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1173                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1174                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1175                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1176                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1177                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1178                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1179                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1180                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1181                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1182                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1183                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1184                 // initialize the samplers to refer to the texture units we use
1185                 p->tex_Texture_First = -1;
1186                 p->tex_Texture_Second = -1;
1187                 p->tex_Texture_GammaRamps = -1;
1188                 p->tex_Texture_Normal = -1;
1189                 p->tex_Texture_Color = -1;
1190                 p->tex_Texture_Gloss = -1;
1191                 p->tex_Texture_Glow = -1;
1192                 p->tex_Texture_SecondaryNormal = -1;
1193                 p->tex_Texture_SecondaryColor = -1;
1194                 p->tex_Texture_SecondaryGloss = -1;
1195                 p->tex_Texture_SecondaryGlow = -1;
1196                 p->tex_Texture_Pants = -1;
1197                 p->tex_Texture_Shirt = -1;
1198                 p->tex_Texture_FogHeightTexture = -1;
1199                 p->tex_Texture_FogMask = -1;
1200                 p->tex_Texture_Lightmap = -1;
1201                 p->tex_Texture_Deluxemap = -1;
1202                 p->tex_Texture_Attenuation = -1;
1203                 p->tex_Texture_Cube = -1;
1204                 p->tex_Texture_Refraction = -1;
1205                 p->tex_Texture_Reflection = -1;
1206                 p->tex_Texture_ShadowMap2D = -1;
1207                 p->tex_Texture_CubeProjection = -1;
1208                 p->tex_Texture_ScreenNormalMap = -1;
1209                 p->tex_Texture_ScreenDiffuse = -1;
1210                 p->tex_Texture_ScreenSpecular = -1;
1211                 p->tex_Texture_ReflectMask = -1;
1212                 p->tex_Texture_ReflectCube = -1;
1213                 p->tex_Texture_BounceGrid = -1;
1214                 sampler = 0;
1215                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1216                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1217                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1218                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1219                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1220                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1221                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1222                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1223                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1224                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1225                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1226                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1227                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1228                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1229                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1230                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1231                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1232                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1233                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1234                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1235                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1236                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1237                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1238                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1239                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1240                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1241                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1242                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1243                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1244                 CHECKGLERROR
1245                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1246         }
1247         else
1248                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1249
1250         // free the strings
1251         if (vertexstring)
1252                 Mem_Free(vertexstring);
1253         if (geometrystring)
1254                 Mem_Free(geometrystring);
1255         if (fragmentstring)
1256                 Mem_Free(fragmentstring);
1257 }
1258
1259 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1260 {
1261         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1262         if (r_glsl_permutation != perm)
1263         {
1264                 r_glsl_permutation = perm;
1265                 if (!r_glsl_permutation->program)
1266                 {
1267                         if (!r_glsl_permutation->compiled)
1268                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1269                         if (!r_glsl_permutation->program)
1270                         {
1271                                 // remove features until we find a valid permutation
1272                                 int i;
1273                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1274                                 {
1275                                         // reduce i more quickly whenever it would not remove any bits
1276                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1277                                         if (!(permutation & j))
1278                                                 continue;
1279                                         permutation -= j;
1280                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1281                                         if (!r_glsl_permutation->compiled)
1282                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1283                                         if (r_glsl_permutation->program)
1284                                                 break;
1285                                 }
1286                                 if (i >= SHADERPERMUTATION_COUNT)
1287                                 {
1288                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1289                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1290                                         qglUseProgram(0);CHECKGLERROR
1291                                         return; // no bit left to clear, entire mode is broken
1292                                 }
1293                         }
1294                 }
1295                 CHECKGLERROR
1296                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1297         }
1298         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1299         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1300         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1301 }
1302
1303 #ifdef SUPPORTD3D
1304
1305 #ifdef SUPPORTD3D
1306 #include <d3d9.h>
1307 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1308 extern D3DCAPS9 vid_d3d9caps;
1309 #endif
1310
1311 struct r_hlsl_permutation_s;
1312 typedef struct r_hlsl_permutation_s
1313 {
1314         /// hash lookup data
1315         struct r_hlsl_permutation_s *hashnext;
1316         unsigned int mode;
1317         unsigned int permutation;
1318
1319         /// indicates if we have tried compiling this permutation already
1320         qboolean compiled;
1321         /// NULL if compilation failed
1322         IDirect3DVertexShader9 *vertexshader;
1323         IDirect3DPixelShader9 *pixelshader;
1324 }
1325 r_hlsl_permutation_t;
1326
1327 typedef enum D3DVSREGISTER_e
1328 {
1329         D3DVSREGISTER_TexMatrix = 0, // float4x4
1330         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1331         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1332         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1333         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1334         D3DVSREGISTER_ModelToLight = 20, // float4x4
1335         D3DVSREGISTER_EyePosition = 24,
1336         D3DVSREGISTER_FogPlane = 25,
1337         D3DVSREGISTER_LightDir = 26,
1338         D3DVSREGISTER_LightPosition = 27,
1339 }
1340 D3DVSREGISTER_t;
1341
1342 typedef enum D3DPSREGISTER_e
1343 {
1344         D3DPSREGISTER_Alpha = 0,
1345         D3DPSREGISTER_BloomBlur_Parameters = 1,
1346         D3DPSREGISTER_ClientTime = 2,
1347         D3DPSREGISTER_Color_Ambient = 3,
1348         D3DPSREGISTER_Color_Diffuse = 4,
1349         D3DPSREGISTER_Color_Specular = 5,
1350         D3DPSREGISTER_Color_Glow = 6,
1351         D3DPSREGISTER_Color_Pants = 7,
1352         D3DPSREGISTER_Color_Shirt = 8,
1353         D3DPSREGISTER_DeferredColor_Ambient = 9,
1354         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1355         D3DPSREGISTER_DeferredColor_Specular = 11,
1356         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1357         D3DPSREGISTER_DeferredMod_Specular = 13,
1358         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1359         D3DPSREGISTER_EyePosition = 15, // unused
1360         D3DPSREGISTER_FogColor = 16,
1361         D3DPSREGISTER_FogHeightFade = 17,
1362         D3DPSREGISTER_FogPlane = 18,
1363         D3DPSREGISTER_FogPlaneViewDist = 19,
1364         D3DPSREGISTER_FogRangeRecip = 20,
1365         D3DPSREGISTER_LightColor = 21,
1366         D3DPSREGISTER_LightDir = 22, // unused
1367         D3DPSREGISTER_LightPosition = 23,
1368         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1369         D3DPSREGISTER_PixelSize = 25,
1370         D3DPSREGISTER_ReflectColor = 26,
1371         D3DPSREGISTER_ReflectFactor = 27,
1372         D3DPSREGISTER_ReflectOffset = 28,
1373         D3DPSREGISTER_RefractColor = 29,
1374         D3DPSREGISTER_Saturation = 30,
1375         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1376         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1377         D3DPSREGISTER_ScreenToDepth = 33,
1378         D3DPSREGISTER_ShadowMap_Parameters = 34,
1379         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1380         D3DPSREGISTER_SpecularPower = 36,
1381         D3DPSREGISTER_UserVec1 = 37,
1382         D3DPSREGISTER_UserVec2 = 38,
1383         D3DPSREGISTER_UserVec3 = 39,
1384         D3DPSREGISTER_UserVec4 = 40,
1385         D3DPSREGISTER_ViewTintColor = 41,
1386         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1387         D3DPSREGISTER_BloomColorSubtract = 43,
1388         D3DPSREGISTER_ViewToLight = 44, // float4x4
1389         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1390         D3DPSREGISTER_NormalmapScrollBlend = 52,
1391         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1392         D3DPSREGISTER_OffsetMapping_Bias = 54,
1393         // next at 54
1394 }
1395 D3DPSREGISTER_t;
1396
1397 /// information about each possible shader permutation
1398 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1399 /// currently selected permutation
1400 r_hlsl_permutation_t *r_hlsl_permutation;
1401 /// storage for permutations linked in the hash table
1402 memexpandablearray_t r_hlsl_permutationarray;
1403
1404 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1405 {
1406         //unsigned int hashdepth = 0;
1407         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1408         r_hlsl_permutation_t *p;
1409         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1410         {
1411                 if (p->mode == mode && p->permutation == permutation)
1412                 {
1413                         //if (hashdepth > 10)
1414                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1415                         return p;
1416                 }
1417                 //hashdepth++;
1418         }
1419         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1420         p->mode = mode;
1421         p->permutation = permutation;
1422         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1423         r_hlsl_permutationhash[mode][hashindex] = p;
1424         //if (hashdepth > 10)
1425         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1426         return p;
1427 }
1428
1429 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1430 {
1431         char *shaderstring;
1432         if (!filename || !filename[0])
1433                 return NULL;
1434         if (!strcmp(filename, "hlsl/default.hlsl"))
1435         {
1436                 if (!hlslshaderstring)
1437                 {
1438                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1439                         if (hlslshaderstring)
1440                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1441                         else
1442                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1443                 }
1444                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1445                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1446                 return shaderstring;
1447         }
1448         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1449         if (shaderstring)
1450         {
1451                 if (printfromdisknotice)
1452                         Con_DPrintf("from disk %s... ", filename);
1453                 return shaderstring;
1454         }
1455         return shaderstring;
1456 }
1457
1458 #include <d3dx9.h>
1459 //#include <d3dx9shader.h>
1460 //#include <d3dx9mesh.h>
1461
1462 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1463 {
1464         DWORD *vsbin = NULL;
1465         DWORD *psbin = NULL;
1466         fs_offset_t vsbinsize;
1467         fs_offset_t psbinsize;
1468 //      IDirect3DVertexShader9 *vs = NULL;
1469 //      IDirect3DPixelShader9 *ps = NULL;
1470         ID3DXBuffer *vslog = NULL;
1471         ID3DXBuffer *vsbuffer = NULL;
1472         ID3DXConstantTable *vsconstanttable = NULL;
1473         ID3DXBuffer *pslog = NULL;
1474         ID3DXBuffer *psbuffer = NULL;
1475         ID3DXConstantTable *psconstanttable = NULL;
1476         int vsresult = 0;
1477         int psresult = 0;
1478         char temp[MAX_INPUTLINE];
1479         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1480         char vabuf[1024];
1481         qboolean debugshader = gl_paranoid.integer != 0;
1482         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1483         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1484         if (!debugshader)
1485         {
1486                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1487                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1488         }
1489         if ((!vsbin && vertstring) || (!psbin && fragstring))
1490         {
1491                 const char* dllnames_d3dx9 [] =
1492                 {
1493                         "d3dx9_43.dll",
1494                         "d3dx9_42.dll",
1495                         "d3dx9_41.dll",
1496                         "d3dx9_40.dll",
1497                         "d3dx9_39.dll",
1498                         "d3dx9_38.dll",
1499                         "d3dx9_37.dll",
1500                         "d3dx9_36.dll",
1501                         "d3dx9_35.dll",
1502                         "d3dx9_34.dll",
1503                         "d3dx9_33.dll",
1504                         "d3dx9_32.dll",
1505                         "d3dx9_31.dll",
1506                         "d3dx9_30.dll",
1507                         "d3dx9_29.dll",
1508                         "d3dx9_28.dll",
1509                         "d3dx9_27.dll",
1510                         "d3dx9_26.dll",
1511                         "d3dx9_25.dll",
1512                         "d3dx9_24.dll",
1513                         NULL
1514                 };
1515                 dllhandle_t d3dx9_dll = NULL;
1516                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1517                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1518                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1519                 dllfunction_t d3dx9_dllfuncs[] =
1520                 {
1521                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1522                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1523                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1524                         {NULL, NULL}
1525                 };
1526                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1527                 {
1528                         DWORD shaderflags = 0;
1529                         if (debugshader)
1530                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1531                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1532                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1533                         if (vertstring && vertstring[0])
1534                         {
1535                                 if (debugshader)
1536                                 {
1537 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1538 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1539                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1540                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1541                                 }
1542                                 else
1543                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1544                                 if (vsbuffer)
1545                                 {
1546                                         vsbinsize = vsbuffer->GetBufferSize();
1547                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1548                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1549                                         vsbuffer->Release();
1550                                 }
1551                                 if (vslog)
1552                                 {
1553                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1554                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1555                                         vslog->Release();
1556                                 }
1557                         }
1558                         if (fragstring && fragstring[0])
1559                         {
1560                                 if (debugshader)
1561                                 {
1562 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1563 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1564                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1565                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1566                                 }
1567                                 else
1568                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1569                                 if (psbuffer)
1570                                 {
1571                                         psbinsize = psbuffer->GetBufferSize();
1572                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1573                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1574                                         psbuffer->Release();
1575                                 }
1576                                 if (pslog)
1577                                 {
1578                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1579                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1580                                         pslog->Release();
1581                                 }
1582                         }
1583                         Sys_UnloadLibrary(&d3dx9_dll);
1584                 }
1585                 else
1586                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1587         }
1588         if (vsbin && psbin)
1589         {
1590                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1591                 if (FAILED(vsresult))
1592                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1593                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1594                 if (FAILED(psresult))
1595                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1596         }
1597         // free the shader data
1598         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1599         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1600 }
1601
1602 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1603 {
1604         int i;
1605         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1606         int vertstring_length = 0;
1607         int geomstring_length = 0;
1608         int fragstring_length = 0;
1609         char *t;
1610         char *vertexstring, *geometrystring, *fragmentstring;
1611         char *vertstring, *geomstring, *fragstring;
1612         char permutationname[256];
1613         char cachename[256];
1614         int vertstrings_count = 0;
1615         int geomstrings_count = 0;
1616         int fragstrings_count = 0;
1617         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1618         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1619         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1620
1621         if (p->compiled)
1622                 return;
1623         p->compiled = true;
1624         p->vertexshader = NULL;
1625         p->pixelshader = NULL;
1626
1627         permutationname[0] = 0;
1628         cachename[0] = 0;
1629         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1630         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1631         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1632
1633         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1634         strlcat(cachename, "hlsl/", sizeof(cachename));
1635
1636         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1637         vertstrings_count = 0;
1638         geomstrings_count = 0;
1639         fragstrings_count = 0;
1640         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1641         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1642         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1643
1644         // the first pretext is which type of shader to compile as
1645         // (later these will all be bound together as a program object)
1646         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1647         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1648         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1649
1650         // the second pretext is the mode (for example a light source)
1651         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1652         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1653         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1654         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1655         strlcat(cachename, modeinfo->name, sizeof(cachename));
1656
1657         // now add all the permutation pretexts
1658         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1659         {
1660                 if (permutation & (1<<i))
1661                 {
1662                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1663                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1664                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1665                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1666                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1667                 }
1668                 else
1669                 {
1670                         // keep line numbers correct
1671                         vertstrings_list[vertstrings_count++] = "\n";
1672                         geomstrings_list[geomstrings_count++] = "\n";
1673                         fragstrings_list[fragstrings_count++] = "\n";
1674                 }
1675         }
1676
1677         // add static parms
1678         R_CompileShader_AddStaticParms(mode, permutation);
1679         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1680         vertstrings_count += shaderstaticparms_count;
1681         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1682         geomstrings_count += shaderstaticparms_count;
1683         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1684         fragstrings_count += shaderstaticparms_count;
1685
1686         // replace spaces in the cachename with _ characters
1687         for (i = 0;cachename[i];i++)
1688                 if (cachename[i] == ' ')
1689                         cachename[i] = '_';
1690
1691         // now append the shader text itself
1692         vertstrings_list[vertstrings_count++] = vertexstring;
1693         geomstrings_list[geomstrings_count++] = geometrystring;
1694         fragstrings_list[fragstrings_count++] = fragmentstring;
1695
1696         // if any sources were NULL, clear the respective list
1697         if (!vertexstring)
1698                 vertstrings_count = 0;
1699         if (!geometrystring)
1700                 geomstrings_count = 0;
1701         if (!fragmentstring)
1702                 fragstrings_count = 0;
1703
1704         vertstring_length = 0;
1705         for (i = 0;i < vertstrings_count;i++)
1706                 vertstring_length += strlen(vertstrings_list[i]);
1707         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1708         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1709                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1710
1711         geomstring_length = 0;
1712         for (i = 0;i < geomstrings_count;i++)
1713                 geomstring_length += strlen(geomstrings_list[i]);
1714         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1715         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1716                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1717
1718         fragstring_length = 0;
1719         for (i = 0;i < fragstrings_count;i++)
1720                 fragstring_length += strlen(fragstrings_list[i]);
1721         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1722         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1723                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1724
1725         // try to load the cached shader, or generate one
1726         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1727
1728         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1729                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1730         else
1731                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1732
1733         // free the strings
1734         if (vertstring)
1735                 Mem_Free(vertstring);
1736         if (geomstring)
1737                 Mem_Free(geomstring);
1738         if (fragstring)
1739                 Mem_Free(fragstring);
1740         if (vertexstring)
1741                 Mem_Free(vertexstring);
1742         if (geometrystring)
1743                 Mem_Free(geometrystring);
1744         if (fragmentstring)
1745                 Mem_Free(fragmentstring);
1746 }
1747
1748 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1749 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1750 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);}
1751 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);}
1752 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);}
1753 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);}
1754
1755 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1756 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1757 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);}
1758 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);}
1759 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);}
1760 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);}
1761
1762 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1763 {
1764         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1765         if (r_hlsl_permutation != perm)
1766         {
1767                 r_hlsl_permutation = perm;
1768                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1769                 {
1770                         if (!r_hlsl_permutation->compiled)
1771                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1772                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1773                         {
1774                                 // remove features until we find a valid permutation
1775                                 int i;
1776                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1777                                 {
1778                                         // reduce i more quickly whenever it would not remove any bits
1779                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1780                                         if (!(permutation & j))
1781                                                 continue;
1782                                         permutation -= j;
1783                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1784                                         if (!r_hlsl_permutation->compiled)
1785                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1786                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1787                                                 break;
1788                                 }
1789                                 if (i >= SHADERPERMUTATION_COUNT)
1790                                 {
1791                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1792                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1793                                         return; // no bit left to clear, entire mode is broken
1794                                 }
1795                         }
1796                 }
1797                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1798                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1799         }
1800         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1801         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1802         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1803 }
1804 #endif
1805
1806 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1807 {
1808         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1809         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1810         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1811         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1812 }
1813
1814 void R_GLSL_Restart_f(void)
1815 {
1816         unsigned int i, limit;
1817         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1818                 Mem_Free(glslshaderstring);
1819         glslshaderstring = NULL;
1820         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1821                 Mem_Free(hlslshaderstring);
1822         hlslshaderstring = NULL;
1823         switch(vid.renderpath)
1824         {
1825         case RENDERPATH_D3D9:
1826 #ifdef SUPPORTD3D
1827                 {
1828                         r_hlsl_permutation_t *p;
1829                         r_hlsl_permutation = NULL;
1830                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1831                         for (i = 0;i < limit;i++)
1832                         {
1833                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1834                                 {
1835                                         if (p->vertexshader)
1836                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1837                                         if (p->pixelshader)
1838                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1839                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1840                                 }
1841                         }
1842                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1843                 }
1844 #endif
1845                 break;
1846         case RENDERPATH_D3D10:
1847                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1848                 break;
1849         case RENDERPATH_D3D11:
1850                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1851                 break;
1852         case RENDERPATH_GL20:
1853         case RENDERPATH_GLES2:
1854                 {
1855                         r_glsl_permutation_t *p;
1856                         r_glsl_permutation = NULL;
1857                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1858                         for (i = 0;i < limit;i++)
1859                         {
1860                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1861                                 {
1862                                         GL_Backend_FreeProgram(p->program);
1863                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1864                                 }
1865                         }
1866                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1867                 }
1868                 break;
1869         case RENDERPATH_GL11:
1870         case RENDERPATH_GL13:
1871         case RENDERPATH_GLES1:
1872                 break;
1873         case RENDERPATH_SOFT:
1874                 break;
1875         }
1876 }
1877
1878 static void R_GLSL_DumpShader_f(void)
1879 {
1880         int i;
1881         qfile_t *file;
1882
1883         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1884         if (file)
1885         {
1886                 FS_Print(file, "/* The engine may define the following macros:\n");
1887                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1888                 for (i = 0;i < SHADERMODE_COUNT;i++)
1889                         FS_Print(file, glslshadermodeinfo[i].pretext);
1890                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1891                         FS_Print(file, shaderpermutationinfo[i].pretext);
1892                 FS_Print(file, "*/\n");
1893                 FS_Print(file, builtinshaderstring);
1894                 FS_Close(file);
1895                 Con_Printf("glsl/default.glsl written\n");
1896         }
1897         else
1898                 Con_Printf("failed to write to glsl/default.glsl\n");
1899
1900         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1901         if (file)
1902         {
1903                 FS_Print(file, "/* The engine may define the following macros:\n");
1904                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1905                 for (i = 0;i < SHADERMODE_COUNT;i++)
1906                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1907                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1908                         FS_Print(file, shaderpermutationinfo[i].pretext);
1909                 FS_Print(file, "*/\n");
1910                 FS_Print(file, builtinhlslshaderstring);
1911                 FS_Close(file);
1912                 Con_Printf("hlsl/default.hlsl written\n");
1913         }
1914         else
1915                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1916 }
1917
1918 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1919 {
1920         unsigned int permutation = 0;
1921         if (r_trippy.integer && !notrippy)
1922                 permutation |= SHADERPERMUTATION_TRIPPY;
1923         permutation |= SHADERPERMUTATION_VIEWTINT;
1924         if (first)
1925                 permutation |= SHADERPERMUTATION_DIFFUSE;
1926         if (second)
1927                 permutation |= SHADERPERMUTATION_SPECULAR;
1928         if (texturemode == GL_MODULATE)
1929                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1930         else if (texturemode == GL_ADD)
1931                 permutation |= SHADERPERMUTATION_GLOW;
1932         else if (texturemode == GL_DECAL)
1933                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1934         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1935                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1936         if (suppresstexalpha)
1937                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1938         if (!second)
1939                 texturemode = GL_MODULATE;
1940         if (vid.allowalphatocoverage)
1941                 GL_AlphaToCoverage(false);
1942         switch (vid.renderpath)
1943         {
1944         case RENDERPATH_D3D9:
1945 #ifdef SUPPORTD3D
1946                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1947                 R_Mesh_TexBind(GL20TU_FIRST , first );
1948                 R_Mesh_TexBind(GL20TU_SECOND, second);
1949                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1950                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1951 #endif
1952                 break;
1953         case RENDERPATH_D3D10:
1954                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1955                 break;
1956         case RENDERPATH_D3D11:
1957                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1958                 break;
1959         case RENDERPATH_GL20:
1960         case RENDERPATH_GLES2:
1961                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1962                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1963                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1964                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1965                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1966                 break;
1967         case RENDERPATH_GL13:
1968         case RENDERPATH_GLES1:
1969                 R_Mesh_TexBind(0, first );
1970                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1971                 R_Mesh_TexBind(1, second);
1972                 if (second)
1973                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1974                 break;
1975         case RENDERPATH_GL11:
1976                 R_Mesh_TexBind(0, first );
1977                 break;
1978         case RENDERPATH_SOFT:
1979                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1980                 R_Mesh_TexBind(GL20TU_FIRST , first );
1981                 R_Mesh_TexBind(GL20TU_SECOND, second);
1982                 break;
1983         }
1984 }
1985
1986 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1987 {
1988         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1989 }
1990
1991 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1992 {
1993         unsigned int permutation = 0;
1994         if (r_trippy.integer && !notrippy)
1995                 permutation |= SHADERPERMUTATION_TRIPPY;
1996         if (depthrgb)
1997                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1998         if (vid.allowalphatocoverage)
1999                 GL_AlphaToCoverage(false);
2000         switch (vid.renderpath)
2001         {
2002         case RENDERPATH_D3D9:
2003 #ifdef SUPPORTD3D
2004                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2005 #endif
2006                 break;
2007         case RENDERPATH_D3D10:
2008                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2009                 break;
2010         case RENDERPATH_D3D11:
2011                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2012                 break;
2013         case RENDERPATH_GL20:
2014         case RENDERPATH_GLES2:
2015                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2016                 break;
2017         case RENDERPATH_GL13:
2018         case RENDERPATH_GLES1:
2019                 R_Mesh_TexBind(0, 0);
2020                 R_Mesh_TexBind(1, 0);
2021                 break;
2022         case RENDERPATH_GL11:
2023                 R_Mesh_TexBind(0, 0);
2024                 break;
2025         case RENDERPATH_SOFT:
2026                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2027                 break;
2028         }
2029 }
2030
2031 void R_SetupShader_ShowDepth(qboolean notrippy)
2032 {
2033         int permutation = 0;
2034         if (r_trippy.integer && !notrippy)
2035                 permutation |= SHADERPERMUTATION_TRIPPY;
2036         if (vid.allowalphatocoverage)
2037                 GL_AlphaToCoverage(false);
2038         switch (vid.renderpath)
2039         {
2040         case RENDERPATH_D3D9:
2041 #ifdef SUPPORTHLSL
2042                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2043 #endif
2044                 break;
2045         case RENDERPATH_D3D10:
2046                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2047                 break;
2048         case RENDERPATH_D3D11:
2049                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2050                 break;
2051         case RENDERPATH_GL20:
2052         case RENDERPATH_GLES2:
2053                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2054                 break;
2055         case RENDERPATH_GL13:
2056         case RENDERPATH_GLES1:
2057                 break;
2058         case RENDERPATH_GL11:
2059                 break;
2060         case RENDERPATH_SOFT:
2061                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2062                 break;
2063         }
2064 }
2065
2066 extern qboolean r_shadow_usingdeferredprepass;
2067 extern rtexture_t *r_shadow_attenuationgradienttexture;
2068 extern rtexture_t *r_shadow_attenuation2dtexture;
2069 extern rtexture_t *r_shadow_attenuation3dtexture;
2070 extern qboolean r_shadow_usingshadowmap2d;
2071 extern qboolean r_shadow_usingshadowmaportho;
2072 extern float r_shadow_shadowmap_texturescale[2];
2073 extern float r_shadow_shadowmap_parameters[4];
2074 extern qboolean r_shadow_shadowmapvsdct;
2075 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2076 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2077 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2078 extern matrix4x4_t r_shadow_shadowmapmatrix;
2079 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2080 extern int r_shadow_prepass_width;
2081 extern int r_shadow_prepass_height;
2082 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2083 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2084 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2085 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2086
2087 #define BLENDFUNC_ALLOWS_COLORMOD      1
2088 #define BLENDFUNC_ALLOWS_FOG           2
2089 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2090 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2091 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2092 static int R_BlendFuncFlags(int src, int dst)
2093 {
2094         int r = 0;
2095
2096         // a blendfunc allows colormod if:
2097         // a) it can never keep the destination pixel invariant, or
2098         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2099         // this is to prevent unintended side effects from colormod
2100
2101         // a blendfunc allows fog if:
2102         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2103         // this is to prevent unintended side effects from fog
2104
2105         // these checks are the output of fogeval.pl
2106
2107         r |= BLENDFUNC_ALLOWS_COLORMOD;
2108         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2109         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2110         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2111         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2112         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2113         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2114         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2115         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2116         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2117         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2118         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2119         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2120         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2121         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2122         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2123         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2124         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2125         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2126         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2127         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2128         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2129
2130         return r;
2131 }
2132
2133 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)
2134 {
2135         // select a permutation of the lighting shader appropriate to this
2136         // combination of texture, entity, light source, and fogging, only use the
2137         // minimum features necessary to avoid wasting rendering time in the
2138         // fragment shader on features that are not being used
2139         unsigned int permutation = 0;
2140         unsigned int mode = 0;
2141         int blendfuncflags;
2142         static float dummy_colormod[3] = {1, 1, 1};
2143         float *colormod = rsurface.colormod;
2144         float m16f[16];
2145         matrix4x4_t tempmatrix;
2146         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2147         if (r_trippy.integer && !notrippy)
2148                 permutation |= SHADERPERMUTATION_TRIPPY;
2149         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2150                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2151         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2152                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2153         if (rsurfacepass == RSURFPASS_BACKGROUND)
2154         {
2155                 // distorted background
2156                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2157                 {
2158                         mode = SHADERMODE_WATER;
2159                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2160                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2161                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2162                         {
2163                                 // this is the right thing to do for wateralpha
2164                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2165                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2166                         }
2167                         else
2168                         {
2169                                 // this is the right thing to do for entity alpha
2170                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2171                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2172                         }
2173                 }
2174                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2175                 {
2176                         mode = SHADERMODE_REFRACTION;
2177                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2178                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2179                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2180                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2181                 }
2182                 else
2183                 {
2184                         mode = SHADERMODE_GENERIC;
2185                         permutation |= SHADERPERMUTATION_DIFFUSE;
2186                         GL_BlendFunc(GL_ONE, GL_ZERO);
2187                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2188                 }
2189                 if (vid.allowalphatocoverage)
2190                         GL_AlphaToCoverage(false);
2191         }
2192         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2193         {
2194                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2195                 {
2196                         switch(rsurface.texture->offsetmapping)
2197                         {
2198                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2199                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2200                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2201                         case OFFSETMAPPING_OFF: break;
2202                         }
2203                 }
2204                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2205                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2206                 // normalmap (deferred prepass), may use alpha test on diffuse
2207                 mode = SHADERMODE_DEFERREDGEOMETRY;
2208                 GL_BlendFunc(GL_ONE, GL_ZERO);
2209                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2210                 if (vid.allowalphatocoverage)
2211                         GL_AlphaToCoverage(false);
2212         }
2213         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2214         {
2215                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2216                 {
2217                         switch(rsurface.texture->offsetmapping)
2218                         {
2219                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2220                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2221                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2222                         case OFFSETMAPPING_OFF: break;
2223                         }
2224                 }
2225                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2226                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2227                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2228                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2229                 // light source
2230                 mode = SHADERMODE_LIGHTSOURCE;
2231                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2232                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2233                 if (diffusescale > 0)
2234                         permutation |= SHADERPERMUTATION_DIFFUSE;
2235                 if (specularscale > 0)
2236                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2237                 if (r_refdef.fogenabled)
2238                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2239                 if (rsurface.texture->colormapping)
2240                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2241                 if (r_shadow_usingshadowmap2d)
2242                 {
2243                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2244                         if(r_shadow_shadowmapvsdct)
2245                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2246
2247                         if (r_shadow_shadowmap2ddepthbuffer)
2248                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2249                 }
2250                 if (rsurface.texture->reflectmasktexture)
2251                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2252                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2253                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2254                 if (vid.allowalphatocoverage)
2255                         GL_AlphaToCoverage(false);
2256         }
2257         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2258         {
2259                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2260                 {
2261                         switch(rsurface.texture->offsetmapping)
2262                         {
2263                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2264                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2265                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2266                         case OFFSETMAPPING_OFF: break;
2267                         }
2268                 }
2269                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2270                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2271                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2272                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2273                 // unshaded geometry (fullbright or ambient model lighting)
2274                 mode = SHADERMODE_FLATCOLOR;
2275                 ambientscale = diffusescale = specularscale = 0;
2276                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2277                         permutation |= SHADERPERMUTATION_GLOW;
2278                 if (r_refdef.fogenabled)
2279                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2280                 if (rsurface.texture->colormapping)
2281                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2282                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2283                 {
2284                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2285                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2286
2287                         if (r_shadow_shadowmap2ddepthbuffer)
2288                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2289                 }
2290                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2291                         permutation |= SHADERPERMUTATION_REFLECTION;
2292                 if (rsurface.texture->reflectmasktexture)
2293                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2294                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2295                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2296                 // when using alphatocoverage, we don't need alphakill
2297                 if (vid.allowalphatocoverage)
2298                 {
2299                         if (r_transparent_alphatocoverage.integer)
2300                         {
2301                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2302                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2303                         }
2304                         else
2305                                 GL_AlphaToCoverage(false);
2306                 }
2307         }
2308         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2309         {
2310                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2311                 {
2312                         switch(rsurface.texture->offsetmapping)
2313                         {
2314                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2315                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2316                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2317                         case OFFSETMAPPING_OFF: break;
2318                         }
2319                 }
2320                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2321                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2322                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2323                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2324                 // directional model lighting
2325                 mode = SHADERMODE_LIGHTDIRECTION;
2326                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2327                         permutation |= SHADERPERMUTATION_GLOW;
2328                 permutation |= SHADERPERMUTATION_DIFFUSE;
2329                 if (specularscale > 0)
2330                         permutation |= SHADERPERMUTATION_SPECULAR;
2331                 if (r_refdef.fogenabled)
2332                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2333                 if (rsurface.texture->colormapping)
2334                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2335                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2336                 {
2337                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2338                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2339
2340                         if (r_shadow_shadowmap2ddepthbuffer)
2341                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2342                 }
2343                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2344                         permutation |= SHADERPERMUTATION_REFLECTION;
2345                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2346                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2347                 if (rsurface.texture->reflectmasktexture)
2348                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2349                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2350                 {
2351                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2352                         if (r_shadow_bouncegriddirectional)
2353                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2354                 }
2355                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2356                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2357                 // when using alphatocoverage, we don't need alphakill
2358                 if (vid.allowalphatocoverage)
2359                 {
2360                         if (r_transparent_alphatocoverage.integer)
2361                         {
2362                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2363                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2364                         }
2365                         else
2366                                 GL_AlphaToCoverage(false);
2367                 }
2368         }
2369         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2370         {
2371                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2372                 {
2373                         switch(rsurface.texture->offsetmapping)
2374                         {
2375                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2376                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2377                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2378                         case OFFSETMAPPING_OFF: break;
2379                         }
2380                 }
2381                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2382                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2383                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2384                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2385                 // ambient model lighting
2386                 mode = SHADERMODE_LIGHTDIRECTION;
2387                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2388                         permutation |= SHADERPERMUTATION_GLOW;
2389                 if (r_refdef.fogenabled)
2390                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2391                 if (rsurface.texture->colormapping)
2392                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2393                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2394                 {
2395                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2396                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2397
2398                         if (r_shadow_shadowmap2ddepthbuffer)
2399                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2400                 }
2401                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2402                         permutation |= SHADERPERMUTATION_REFLECTION;
2403                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2404                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2405                 if (rsurface.texture->reflectmasktexture)
2406                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2407                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2408                 {
2409                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2410                         if (r_shadow_bouncegriddirectional)
2411                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2412                 }
2413                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2414                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2415                 // when using alphatocoverage, we don't need alphakill
2416                 if (vid.allowalphatocoverage)
2417                 {
2418                         if (r_transparent_alphatocoverage.integer)
2419                         {
2420                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2421                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2422                         }
2423                         else
2424                                 GL_AlphaToCoverage(false);
2425                 }
2426         }
2427         else
2428         {
2429                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2430                 {
2431                         switch(rsurface.texture->offsetmapping)
2432                         {
2433                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2434                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2435                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2436                         case OFFSETMAPPING_OFF: break;
2437                         }
2438                 }
2439                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2440                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2441                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2442                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2443                 // lightmapped wall
2444                 if ((rsurface.texture->glowtexture || rsurface.texture->backgroundglowtexture) && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2445                         permutation |= SHADERPERMUTATION_GLOW;
2446                 if (r_refdef.fogenabled)
2447                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2448                 if (rsurface.texture->colormapping)
2449                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2450                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2451                 {
2452                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2453                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2454
2455                         if (r_shadow_shadowmap2ddepthbuffer)
2456                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2457                 }
2458                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2459                         permutation |= SHADERPERMUTATION_REFLECTION;
2460                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2461                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2462                 if (rsurface.texture->reflectmasktexture)
2463                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2464                 if (FAKELIGHT_ENABLED)
2465                 {
2466                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2467                         mode = SHADERMODE_FAKELIGHT;
2468                         permutation |= SHADERPERMUTATION_DIFFUSE;
2469                         if (specularscale > 0)
2470                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2471                 }
2472                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2473                 {
2474                         // deluxemapping (light direction texture)
2475                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2476                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2477                         else
2478                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2479                         permutation |= SHADERPERMUTATION_DIFFUSE;
2480                         if (specularscale > 0)
2481                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2482                 }
2483                 else if (r_glsl_deluxemapping.integer >= 2)
2484                 {
2485                         // fake deluxemapping (uniform light direction in tangentspace)
2486                         if (rsurface.uselightmaptexture)
2487                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2488                         else
2489                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2490                         permutation |= SHADERPERMUTATION_DIFFUSE;
2491                         if (specularscale > 0)
2492                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2493                 }
2494                 else if (rsurface.uselightmaptexture)
2495                 {
2496                         // ordinary lightmapping (q1bsp, q3bsp)
2497                         mode = SHADERMODE_LIGHTMAP;
2498                 }
2499                 else
2500                 {
2501                         // ordinary vertex coloring (q3bsp)
2502                         mode = SHADERMODE_VERTEXCOLOR;
2503                 }
2504                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2505                 {
2506                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2507                         if (r_shadow_bouncegriddirectional)
2508                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2509                 }
2510                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2511                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2512                 // when using alphatocoverage, we don't need alphakill
2513                 if (vid.allowalphatocoverage)
2514                 {
2515                         if (r_transparent_alphatocoverage.integer)
2516                         {
2517                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2518                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2519                         }
2520                         else
2521                                 GL_AlphaToCoverage(false);
2522                 }
2523         }
2524         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2525                 colormod = dummy_colormod;
2526         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2527                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2528         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2529                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2530         switch(vid.renderpath)
2531         {
2532         case RENDERPATH_D3D9:
2533 #ifdef SUPPORTD3D
2534                 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);
2535                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2536                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2537                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2538                 if (mode == SHADERMODE_LIGHTSOURCE)
2539                 {
2540                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2541                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2542                 }
2543                 else
2544                 {
2545                         if (mode == SHADERMODE_LIGHTDIRECTION)
2546                         {
2547                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2548                         }
2549                 }
2550                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2551                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2552                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2553                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2554                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2555
2556                 if (mode == SHADERMODE_LIGHTSOURCE)
2557                 {
2558                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2559                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2560                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2561                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2562                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2563
2564                         // additive passes are only darkened by fog, not tinted
2565                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2566                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2567                 }
2568                 else
2569                 {
2570                         if (mode == SHADERMODE_FLATCOLOR)
2571                         {
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2573                         }
2574                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2575                         {
2576                                 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]);
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2578                                 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);
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2581                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2582                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2583                         }
2584                         else
2585                         {
2586                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2587                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2588                                 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);
2589                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2590                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2591                         }
2592                         // additive passes are only darkened by fog, not tinted
2593                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2594                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2595                         else
2596                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2597                         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);
2598                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2599                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2600                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2601                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2602                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2603                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2604                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2605                         if (mode == SHADERMODE_WATER)
2606                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2607                 }
2608                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2609                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2610                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2611                 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));
2612                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2613                 if (rsurface.texture->pantstexture)
2614                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2615                 else
2616                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2617                 if (rsurface.texture->shirttexture)
2618                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2619                 else
2620                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2621                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2622                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2623                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2624                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2625                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2626                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2627                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2628                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2629                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2630                         );
2631                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2632                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2633                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2634                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2635
2636                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2637                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2638                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2639                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2640                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2641                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2642                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2643                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2644                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2645                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2646                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2647                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2648                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2649                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2650                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2651                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2652                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2653                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2654                 {
2655                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2656                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2657                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2658                 }
2659                 else
2660                 {
2661                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2662                 }
2663 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2664                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2665                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2666                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2667                 {
2668                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2669                         if (rsurface.rtlight)
2670                         {
2671                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2672                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2673                         }
2674                 }
2675 #endif
2676                 break;
2677         case RENDERPATH_D3D10:
2678                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2679                 break;
2680         case RENDERPATH_D3D11:
2681                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2682                 break;
2683         case RENDERPATH_GL20:
2684         case RENDERPATH_GLES2:
2685                 if (!vid.useinterleavedarrays)
2686                 {
2687                         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);
2688                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2689                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2690                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2691                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2692                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2693                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2694                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2695                 }
2696                 else
2697                 {
2698                         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);
2699                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2700                 }
2701                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2702                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2703                 if (mode == SHADERMODE_LIGHTSOURCE)
2704                 {
2705                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2706                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2707                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2708                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2709                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2710                         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);
2711         
2712                         // additive passes are only darkened by fog, not tinted
2713                         if (r_glsl_permutation->loc_FogColor >= 0)
2714                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2715                         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);
2716                 }
2717                 else
2718                 {
2719                         if (mode == SHADERMODE_FLATCOLOR)
2720                         {
2721                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2722                         }
2723                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2724                         {
2725                                 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]);
2726                                 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]);
2727                                 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);
2728                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2729                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2730                                 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]);
2731                                 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]);
2732                         }
2733                         else
2734                         {
2735                                 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]);
2736                                 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]);
2737                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2738                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2739                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2740                         }
2741                         // additive passes are only darkened by fog, not tinted
2742                         if (r_glsl_permutation->loc_FogColor >= 0)
2743                         {
2744                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2745                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2746                                 else
2747                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2748                         }
2749                         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);
2750                         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]);
2751                         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]);
2752                         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]);
2753                         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]);
2754                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2755                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2756                         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);
2757                         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]);
2758                 }
2759                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2760                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2761                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2762                 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]);
2763                 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]);
2764
2765                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2766                 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));
2767                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2768                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2769                 {
2770                         if (rsurface.texture->pantstexture)
2771                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2772                         else
2773                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2774                 }
2775                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2776                 {
2777                         if (rsurface.texture->shirttexture)
2778                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2779                         else
2780                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2781                 }
2782                 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]);
2783                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2784                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2785                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2786                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2787                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2788                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2789                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2790                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2791                         );
2792                 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);
2793                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2794                 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]);
2795                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2796                 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);}
2797                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2798
2799                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2800                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2801                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2802                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2803                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2804                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2805                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2806                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2807                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2808                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2809                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2810                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2811                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2812                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2813                 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);
2814                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2815                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2816                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2817                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2818                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2819                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2820                 {
2821                         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);
2822                         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);
2823                         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);
2824                 }
2825                 else
2826                 {
2827                         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);
2828                 }
2829                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2830                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2831                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2832                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2833                 {
2834                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2835                         if (rsurface.rtlight)
2836                         {
2837                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2838                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2839                         }
2840                 }
2841                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2842                 CHECKGLERROR
2843                 break;
2844         case RENDERPATH_GL11:
2845         case RENDERPATH_GL13:
2846         case RENDERPATH_GLES1:
2847                 break;
2848         case RENDERPATH_SOFT:
2849                 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);
2850                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2851                 R_SetupShader_SetPermutationSoft(mode, permutation);
2852                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2853                 if (mode == SHADERMODE_LIGHTSOURCE)
2854                 {
2855                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2856                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2857                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2858                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2859                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2860                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2861         
2862                         // additive passes are only darkened by fog, not tinted
2863                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2864                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2865                 }
2866                 else
2867                 {
2868                         if (mode == SHADERMODE_FLATCOLOR)
2869                         {
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2871                         }
2872                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2873                         {
2874                                 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]);
2875                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2876                                 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);
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2879                                 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]);
2880                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2881                         }
2882                         else
2883                         {
2884                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2885                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2886                                 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);
2887                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2888                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2889                         }
2890                         // additive passes are only darkened by fog, not tinted
2891                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2892                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2893                         else
2894                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2895                         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);
2896                         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]);
2897                         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]);
2898                         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]);
2899                         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]);
2900                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2901                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2902                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2903                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2904                 }
2905                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2906                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2907                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2908                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2909                 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]);
2910
2911                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2912                 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));
2913                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2914                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2915                 {
2916                         if (rsurface.texture->pantstexture)
2917                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2918                         else
2919                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2920                 }
2921                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2922                 {
2923                         if (rsurface.texture->shirttexture)
2924                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2925                         else
2926                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2927                 }
2928                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2929                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2930                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2931                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2932                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2933                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2934                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2935                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2936                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2937                         );
2938                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2939                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2940                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2941                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2942
2943                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2944                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2945                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2946                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2947                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2948                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2949                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2950                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2951                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2952                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2953                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2954                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2955                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2956                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2957                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2958                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2959                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2960                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2961                 {
2962                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2963                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2964                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2965                 }
2966                 else
2967                 {
2968                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2969                 }
2970 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2971                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2972                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2973                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2974                 {
2975                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2976                         if (rsurface.rtlight)
2977                         {
2978                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2979                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2980                         }
2981                 }
2982                 break;
2983         }
2984 }
2985
2986 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2987 {
2988         // select a permutation of the lighting shader appropriate to this
2989         // combination of texture, entity, light source, and fogging, only use the
2990         // minimum features necessary to avoid wasting rendering time in the
2991         // fragment shader on features that are not being used
2992         unsigned int permutation = 0;
2993         unsigned int mode = 0;
2994         const float *lightcolorbase = rtlight->currentcolor;
2995         float ambientscale = rtlight->ambientscale;
2996         float diffusescale = rtlight->diffusescale;
2997         float specularscale = rtlight->specularscale;
2998         // this is the location of the light in view space
2999         vec3_t viewlightorigin;
3000         // this transforms from view space (camera) to light space (cubemap)
3001         matrix4x4_t viewtolight;
3002         matrix4x4_t lighttoview;
3003         float viewtolight16f[16];
3004         // light source
3005         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
3006         if (rtlight->currentcubemap != r_texture_whitecube)
3007                 permutation |= SHADERPERMUTATION_CUBEFILTER;
3008         if (diffusescale > 0)
3009                 permutation |= SHADERPERMUTATION_DIFFUSE;
3010         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3011                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3012         if (r_shadow_usingshadowmap2d)
3013         {
3014                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3015                 if (r_shadow_shadowmapvsdct)
3016                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3017
3018                 if (r_shadow_shadowmap2ddepthbuffer)
3019                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3020         }
3021         if (vid.allowalphatocoverage)
3022                 GL_AlphaToCoverage(false);
3023         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3024         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3025         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3026         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3027         switch(vid.renderpath)
3028         {
3029         case RENDERPATH_D3D9:
3030 #ifdef SUPPORTD3D
3031                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3032                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3033                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3034                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3035                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3036                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3037                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3038                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3039                 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);
3040                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3041                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3042
3043                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3044                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3045                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3046                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3047                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3048 #endif
3049                 break;
3050         case RENDERPATH_D3D10:
3051                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3052                 break;
3053         case RENDERPATH_D3D11:
3054                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3055                 break;
3056         case RENDERPATH_GL20:
3057         case RENDERPATH_GLES2:
3058                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3059                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3060                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3061                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3062                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3063                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3064                 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]);
3065                 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]);
3066                 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);
3067                 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]);
3068                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3069
3070                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3071                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3072                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3073                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3074                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3075                 break;
3076         case RENDERPATH_GL11:
3077         case RENDERPATH_GL13:
3078         case RENDERPATH_GLES1:
3079                 break;
3080         case RENDERPATH_SOFT:
3081                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3082                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3083                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3084                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3085                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3086                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3087                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3088                 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]);
3089                 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);
3090                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3091                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3092
3093                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3094                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3095                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3096                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3097                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3098                 break;
3099         }
3100 }
3101
3102 #define SKINFRAME_HASH 1024
3103
3104 typedef struct
3105 {
3106         int loadsequence; // incremented each level change
3107         memexpandablearray_t array;
3108         skinframe_t *hash[SKINFRAME_HASH];
3109 }
3110 r_skinframe_t;
3111 r_skinframe_t r_skinframe;
3112
3113 void R_SkinFrame_PrepareForPurge(void)
3114 {
3115         r_skinframe.loadsequence++;
3116         // wrap it without hitting zero
3117         if (r_skinframe.loadsequence >= 200)
3118                 r_skinframe.loadsequence = 1;
3119 }
3120
3121 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3122 {
3123         if (!skinframe)
3124                 return;
3125         // mark the skinframe as used for the purging code
3126         skinframe->loadsequence = r_skinframe.loadsequence;
3127 }
3128
3129 void R_SkinFrame_Purge(void)
3130 {
3131         int i;
3132         skinframe_t *s;
3133         for (i = 0;i < SKINFRAME_HASH;i++)
3134         {
3135                 for (s = r_skinframe.hash[i];s;s = s->next)
3136                 {
3137                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3138                         {
3139                                 if (s->merged == s->base)
3140                                         s->merged = NULL;
3141                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3142                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3143                                 R_PurgeTexture(s->merged);s->merged = NULL;
3144                                 R_PurgeTexture(s->base  );s->base   = NULL;
3145                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3146                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3147                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3148                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3149                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3150                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3151                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3152                                 s->loadsequence = 0;
3153                         }
3154                 }
3155         }
3156 }
3157
3158 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3159         skinframe_t *item;
3160         char basename[MAX_QPATH];
3161
3162         Image_StripImageExtension(name, basename, sizeof(basename));
3163
3164         if( last == NULL ) {
3165                 int hashindex;
3166                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3167                 item = r_skinframe.hash[hashindex];
3168         } else {
3169                 item = last->next;
3170         }
3171
3172         // linearly search through the hash bucket
3173         for( ; item ; item = item->next ) {
3174                 if( !strcmp( item->basename, basename ) ) {
3175                         return item;
3176                 }
3177         }
3178         return NULL;
3179 }
3180
3181 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3182 {
3183         skinframe_t *item;
3184         int hashindex;
3185         char basename[MAX_QPATH];
3186
3187         Image_StripImageExtension(name, basename, sizeof(basename));
3188
3189         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3190         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3191                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3192                         break;
3193
3194         if (!item) {
3195                 rtexture_t *dyntexture;
3196                 // check whether its a dynamic texture
3197                 dyntexture = CL_GetDynTexture( basename );
3198                 if (!add && !dyntexture)
3199                         return NULL;
3200                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3201                 memset(item, 0, sizeof(*item));
3202                 strlcpy(item->basename, basename, sizeof(item->basename));
3203                 item->base = dyntexture; // either NULL or dyntexture handle
3204                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3205                 item->comparewidth = comparewidth;
3206                 item->compareheight = compareheight;
3207                 item->comparecrc = comparecrc;
3208                 item->next = r_skinframe.hash[hashindex];
3209                 r_skinframe.hash[hashindex] = item;
3210         }
3211         else if (textureflags & TEXF_FORCE_RELOAD)
3212         {
3213                 rtexture_t *dyntexture;
3214                 // check whether its a dynamic texture
3215                 dyntexture = CL_GetDynTexture( basename );
3216                 if (!add && !dyntexture)
3217                         return NULL;
3218                 if (item->merged == item->base)
3219                         item->merged = NULL;
3220                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3221                 R_PurgeTexture(item->stain );item->stain  = NULL;
3222                 R_PurgeTexture(item->merged);item->merged = NULL;
3223                 R_PurgeTexture(item->base  );item->base   = NULL;
3224                 R_PurgeTexture(item->pants );item->pants  = NULL;
3225                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3226                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3227                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3228                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3229                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3230         R_PurgeTexture(item->reflect);item->reflect = NULL;
3231                 item->loadsequence = 0;
3232         }
3233         else if( item->base == NULL )
3234         {
3235                 rtexture_t *dyntexture;
3236                 // check whether its a dynamic texture
3237                 // 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]
3238                 dyntexture = CL_GetDynTexture( basename );
3239                 item->base = dyntexture; // either NULL or dyntexture handle
3240         }
3241
3242         R_SkinFrame_MarkUsed(item);
3243         return item;
3244 }
3245
3246 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3247         { \
3248                 unsigned long long avgcolor[5], wsum; \
3249                 int pix, comp, w; \
3250                 avgcolor[0] = 0; \
3251                 avgcolor[1] = 0; \
3252                 avgcolor[2] = 0; \
3253                 avgcolor[3] = 0; \
3254                 avgcolor[4] = 0; \
3255                 wsum = 0; \
3256                 for(pix = 0; pix < cnt; ++pix) \
3257                 { \
3258                         w = 0; \
3259                         for(comp = 0; comp < 3; ++comp) \
3260                                 w += getpixel; \
3261                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3262                         { \
3263                                 ++wsum; \
3264                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3265                                 w = getpixel; \
3266                                 for(comp = 0; comp < 3; ++comp) \
3267                                         avgcolor[comp] += getpixel * w; \
3268                                 avgcolor[3] += w; \
3269                         } \
3270                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3271                         avgcolor[4] += getpixel; \
3272                 } \
3273                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3274                         avgcolor[3] = 1; \
3275                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3276                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3277                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3278                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3279         }
3280
3281 extern cvar_t gl_picmip;
3282 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3283 {
3284         int j;
3285         unsigned char *pixels;
3286         unsigned char *bumppixels;
3287         unsigned char *basepixels = NULL;
3288         int basepixels_width = 0;
3289         int basepixels_height = 0;
3290         skinframe_t *skinframe;
3291         rtexture_t *ddsbase = NULL;
3292         qboolean ddshasalpha = false;
3293         float ddsavgcolor[4];
3294         char basename[MAX_QPATH];
3295         int miplevel = R_PicmipForFlags(textureflags);
3296         int savemiplevel = miplevel;
3297         int mymiplevel;
3298         char vabuf[1024];
3299
3300         if (cls.state == ca_dedicated)
3301                 return NULL;
3302
3303         // return an existing skinframe if already loaded
3304         // if loading of the first image fails, don't make a new skinframe as it
3305         // would cause all future lookups of this to be missing
3306         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3307         if (skinframe && skinframe->base)
3308                 return skinframe;
3309
3310         Image_StripImageExtension(name, basename, sizeof(basename));
3311
3312         // check for DDS texture file first
3313         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel, false)))
3314         {
3315                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3316                 if (basepixels == NULL)
3317                         return NULL;
3318         }
3319
3320         // FIXME handle miplevel
3321
3322         if (developer_loading.integer)
3323                 Con_Printf("loading skin \"%s\"\n", name);
3324
3325         // we've got some pixels to store, so really allocate this new texture now
3326         if (!skinframe)
3327                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3328         textureflags &= ~TEXF_FORCE_RELOAD;
3329         skinframe->stain = NULL;
3330         skinframe->merged = NULL;
3331         skinframe->base = NULL;
3332         skinframe->pants = NULL;
3333         skinframe->shirt = NULL;
3334         skinframe->nmap = NULL;
3335         skinframe->gloss = NULL;
3336         skinframe->glow = NULL;
3337         skinframe->fog = NULL;
3338         skinframe->reflect = NULL;
3339         skinframe->hasalpha = false;
3340
3341         if (ddsbase)
3342         {
3343                 skinframe->base = ddsbase;
3344                 skinframe->hasalpha = ddshasalpha;
3345                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3346                 if (r_loadfog && skinframe->hasalpha)
3347                         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);
3348                 //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]);
3349         }
3350         else
3351         {
3352                 basepixels_width = image_width;
3353                 basepixels_height = image_height;
3354                 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);
3355                 if (textureflags & TEXF_ALPHA)
3356                 {
3357                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3358                         {
3359                                 if (basepixels[j] < 255)
3360                                 {
3361                                         skinframe->hasalpha = true;
3362                                         break;
3363                                 }
3364                         }
3365                         if (r_loadfog && skinframe->hasalpha)
3366                         {
3367                                 // has transparent pixels
3368                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3369                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3370                                 {
3371                                         pixels[j+0] = 255;
3372                                         pixels[j+1] = 255;
3373                                         pixels[j+2] = 255;
3374                                         pixels[j+3] = basepixels[j+3];
3375                                 }
3376                                 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);
3377                                 Mem_Free(pixels);
3378                         }
3379                 }
3380                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3381 #ifndef USE_GLES2
3382                 //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]);
3383                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3384                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3385                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3386                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3387 #endif
3388         }
3389
3390         if (r_loaddds)
3391         {
3392                 mymiplevel = savemiplevel;
3393                 if (r_loadnormalmap)
3394                         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);
3395                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3396                 if (r_loadgloss)
3397                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3398                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3399                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3400                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel, true);
3401         }
3402
3403         // _norm is the name used by tenebrae and has been adopted as standard
3404         if (r_loadnormalmap && skinframe->nmap == NULL)
3405         {
3406                 mymiplevel = savemiplevel;
3407                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3408                 {
3409                         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);
3410                         Mem_Free(pixels);
3411                         pixels = NULL;
3412                 }
3413                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3414                 {
3415                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3416                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3417                         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);
3418                         Mem_Free(pixels);
3419                         Mem_Free(bumppixels);
3420                 }
3421                 else if (r_shadow_bumpscale_basetexture.value > 0)
3422                 {
3423                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3424                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3425                         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);
3426                         Mem_Free(pixels);
3427                 }
3428 #ifndef USE_GLES2
3429                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3430                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3431 #endif
3432         }
3433
3434         // _luma is supported only for tenebrae compatibility
3435         // _glow is the preferred name
3436         mymiplevel = savemiplevel;
3437         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))))
3438         {
3439                 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);
3440 #ifndef USE_GLES2
3441                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3442                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3443 #endif
3444                 Mem_Free(pixels);pixels = NULL;
3445         }
3446
3447         mymiplevel = savemiplevel;
3448         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3449         {
3450                 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);
3451 #ifndef USE_GLES2
3452                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3453                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3454 #endif
3455                 Mem_Free(pixels);
3456                 pixels = NULL;
3457         }
3458
3459         mymiplevel = savemiplevel;
3460         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3461         {
3462                 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);
3463 #ifndef USE_GLES2
3464                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3465                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3466 #endif
3467                 Mem_Free(pixels);
3468                 pixels = NULL;
3469         }
3470
3471         mymiplevel = savemiplevel;
3472         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3473         {
3474                 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);
3475 #ifndef USE_GLES2
3476                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3477                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3478 #endif
3479                 Mem_Free(pixels);
3480                 pixels = NULL;
3481         }
3482
3483         mymiplevel = savemiplevel;
3484         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3485         {
3486                 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);
3487 #ifndef USE_GLES2
3488                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3489                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3490 #endif
3491                 Mem_Free(pixels);
3492                 pixels = NULL;
3493         }
3494
3495         if (basepixels)
3496                 Mem_Free(basepixels);
3497
3498         return skinframe;
3499 }
3500
3501 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3502 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3503 {
3504         int i;
3505         unsigned char *temp1, *temp2;
3506         skinframe_t *skinframe;
3507         char vabuf[1024];
3508
3509         if (cls.state == ca_dedicated)
3510                 return NULL;
3511
3512         // if already loaded just return it, otherwise make a new skinframe
3513         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3514         if (skinframe && skinframe->base)
3515                 return skinframe;
3516         textureflags &= ~TEXF_FORCE_RELOAD;
3517
3518         skinframe->stain = NULL;
3519         skinframe->merged = NULL;
3520         skinframe->base = NULL;
3521         skinframe->pants = NULL;
3522         skinframe->shirt = NULL;
3523         skinframe->nmap = NULL;
3524         skinframe->gloss = NULL;
3525         skinframe->glow = NULL;
3526         skinframe->fog = NULL;
3527         skinframe->reflect = NULL;
3528         skinframe->hasalpha = false;
3529
3530         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3531         if (!skindata)
3532                 return NULL;
3533
3534         if (developer_loading.integer)
3535                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3536
3537         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3538         {
3539                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3540                 temp2 = temp1 + width * height * 4;
3541                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3542                 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);
3543                 Mem_Free(temp1);
3544         }
3545         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3546         if (textureflags & TEXF_ALPHA)
3547         {
3548                 for (i = 3;i < width * height * 4;i += 4)
3549                 {
3550                         if (skindata[i] < 255)
3551                         {
3552                                 skinframe->hasalpha = true;
3553                                 break;
3554                         }
3555                 }
3556                 if (r_loadfog && skinframe->hasalpha)
3557                 {
3558                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3559                         memcpy(fogpixels, skindata, width * height * 4);
3560                         for (i = 0;i < width * height * 4;i += 4)
3561                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3562                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3563                         Mem_Free(fogpixels);
3564                 }
3565         }
3566
3567         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3568         //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]);
3569
3570         return skinframe;
3571 }
3572
3573 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3574 {
3575         int i;
3576         int featuresmask;
3577         skinframe_t *skinframe;
3578
3579         if (cls.state == ca_dedicated)
3580                 return NULL;
3581
3582         // if already loaded just return it, otherwise make a new skinframe
3583         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3584         if (skinframe && skinframe->base)
3585                 return skinframe;
3586         textureflags &= ~TEXF_FORCE_RELOAD;
3587
3588         skinframe->stain = NULL;
3589         skinframe->merged = NULL;
3590         skinframe->base = NULL;
3591         skinframe->pants = NULL;
3592         skinframe->shirt = NULL;
3593         skinframe->nmap = NULL;
3594         skinframe->gloss = NULL;
3595         skinframe->glow = NULL;
3596         skinframe->fog = NULL;
3597         skinframe->reflect = NULL;
3598         skinframe->hasalpha = false;
3599
3600         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3601         if (!skindata)
3602                 return NULL;
3603
3604         if (developer_loading.integer)
3605                 Con_Printf("loading quake skin \"%s\"\n", name);
3606
3607         // 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)
3608         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3609         memcpy(skinframe->qpixels, skindata, width*height);
3610         skinframe->qwidth = width;
3611         skinframe->qheight = height;
3612
3613         featuresmask = 0;
3614         for (i = 0;i < width * height;i++)
3615                 featuresmask |= palette_featureflags[skindata[i]];
3616
3617         skinframe->hasalpha = false;
3618         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3619         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3620         skinframe->qgeneratemerged = true;
3621         skinframe->qgeneratebase = skinframe->qhascolormapping;
3622         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3623
3624         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3625         //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]);
3626
3627         return skinframe;
3628 }
3629
3630 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3631 {
3632         int width;
3633         int height;
3634         unsigned char *skindata;
3635         char vabuf[1024];
3636
3637         if (!skinframe->qpixels)
3638                 return;
3639
3640         if (!skinframe->qhascolormapping)
3641                 colormapped = false;
3642
3643         if (colormapped)
3644         {
3645                 if (!skinframe->qgeneratebase)
3646                         return;
3647         }
3648         else
3649         {
3650                 if (!skinframe->qgeneratemerged)
3651                         return;
3652         }
3653
3654         width = skinframe->qwidth;
3655         height = skinframe->qheight;
3656         skindata = skinframe->qpixels;
3657
3658         if (skinframe->qgeneratenmap)
3659         {
3660                 unsigned char *temp1, *temp2;
3661                 skinframe->qgeneratenmap = false;
3662                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3663                 temp2 = temp1 + width * height * 4;
3664                 // use either a custom palette or the quake palette
3665                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3666                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3667                 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);
3668                 Mem_Free(temp1);
3669         }
3670
3671         if (skinframe->qgenerateglow)
3672         {
3673                 skinframe->qgenerateglow = false;
3674                 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
3675         }
3676
3677         if (colormapped)
3678         {
3679                 skinframe->qgeneratebase = false;
3680                 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);
3681                 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);
3682                 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);
3683         }
3684         else
3685         {
3686                 skinframe->qgeneratemerged = false;
3687                 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);
3688         }
3689
3690         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3691         {
3692                 Mem_Free(skinframe->qpixels);
3693                 skinframe->qpixels = NULL;
3694         }
3695 }
3696
3697 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)
3698 {
3699         int i;
3700         skinframe_t *skinframe;
3701         char vabuf[1024];
3702
3703         if (cls.state == ca_dedicated)
3704                 return NULL;
3705
3706         // if already loaded just return it, otherwise make a new skinframe
3707         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3708         if (skinframe && skinframe->base)
3709                 return skinframe;
3710         textureflags &= ~TEXF_FORCE_RELOAD;
3711
3712         skinframe->stain = NULL;
3713         skinframe->merged = NULL;
3714         skinframe->base = NULL;
3715         skinframe->pants = NULL;
3716         skinframe->shirt = NULL;
3717         skinframe->nmap = NULL;
3718         skinframe->gloss = NULL;
3719         skinframe->glow = NULL;
3720         skinframe->fog = NULL;
3721         skinframe->reflect = NULL;
3722         skinframe->hasalpha = false;
3723
3724         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3725         if (!skindata)
3726                 return NULL;
3727
3728         if (developer_loading.integer)
3729                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3730
3731         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3732         if (textureflags & TEXF_ALPHA)
3733         {
3734                 for (i = 0;i < width * height;i++)
3735                 {
3736                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3737                         {
3738                                 skinframe->hasalpha = true;
3739                                 break;
3740                         }
3741                 }
3742                 if (r_loadfog && skinframe->hasalpha)
3743                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3744         }
3745
3746         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3747         //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]);
3748
3749         return skinframe;
3750 }
3751
3752 skinframe_t *R_SkinFrame_LoadMissing(void)
3753 {
3754         skinframe_t *skinframe;
3755
3756         if (cls.state == ca_dedicated)
3757                 return NULL;
3758
3759         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3760         skinframe->stain = NULL;
3761         skinframe->merged = NULL;
3762         skinframe->base = NULL;
3763         skinframe->pants = NULL;
3764         skinframe->shirt = NULL;
3765         skinframe->nmap = NULL;
3766         skinframe->gloss = NULL;
3767         skinframe->glow = NULL;
3768         skinframe->fog = NULL;
3769         skinframe->reflect = NULL;
3770         skinframe->hasalpha = false;
3771
3772         skinframe->avgcolor[0] = rand() / RAND_MAX;
3773         skinframe->avgcolor[1] = rand() / RAND_MAX;
3774         skinframe->avgcolor[2] = rand() / RAND_MAX;
3775         skinframe->avgcolor[3] = 1;
3776
3777         return skinframe;
3778 }
3779
3780 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3781 typedef struct suffixinfo_s
3782 {
3783         const char *suffix;
3784         qboolean flipx, flipy, flipdiagonal;
3785 }
3786 suffixinfo_t;
3787 static suffixinfo_t suffix[3][6] =
3788 {
3789         {
3790                 {"px",   false, false, false},
3791                 {"nx",   false, false, false},
3792                 {"py",   false, false, false},
3793                 {"ny",   false, false, false},
3794                 {"pz",   false, false, false},
3795                 {"nz",   false, false, false}
3796         },
3797         {
3798                 {"posx", false, false, false},
3799                 {"negx", false, false, false},
3800                 {"posy", false, false, false},
3801                 {"negy", false, false, false},
3802                 {"posz", false, false, false},
3803                 {"negz", false, false, false}
3804         },
3805         {
3806                 {"rt",    true, false,  true},
3807                 {"lf",   false,  true,  true},
3808                 {"ft",    true,  true, false},
3809                 {"bk",   false, false, false},
3810                 {"up",    true, false,  true},
3811                 {"dn",    true, false,  true}
3812         }
3813 };
3814
3815 static int componentorder[4] = {0, 1, 2, 3};
3816
3817 static rtexture_t *R_LoadCubemap(const char *basename)
3818 {
3819         int i, j, cubemapsize;
3820         unsigned char *cubemappixels, *image_buffer;
3821         rtexture_t *cubemaptexture;
3822         char name[256];
3823         // must start 0 so the first loadimagepixels has no requested width/height
3824         cubemapsize = 0;
3825         cubemappixels = NULL;
3826         cubemaptexture = NULL;
3827         // keep trying different suffix groups (posx, px, rt) until one loads
3828         for (j = 0;j < 3 && !cubemappixels;j++)
3829         {
3830                 // load the 6 images in the suffix group
3831                 for (i = 0;i < 6;i++)
3832                 {
3833                         // generate an image name based on the base and and suffix
3834                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3835                         // load it
3836                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3837                         {
3838                                 // an image loaded, make sure width and height are equal
3839                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3840                                 {
3841                                         // if this is the first image to load successfully, allocate the cubemap memory
3842                                         if (!cubemappixels && image_width >= 1)
3843                                         {
3844                                                 cubemapsize = image_width;
3845                                                 // note this clears to black, so unavailable sides are black
3846                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3847                                         }
3848                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3849                                         if (cubemappixels)
3850                                                 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);
3851                                 }
3852                                 else
3853                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3854                                 // free the image
3855                                 Mem_Free(image_buffer);
3856                         }
3857                 }
3858         }
3859         // if a cubemap loaded, upload it
3860         if (cubemappixels)
3861         {
3862                 if (developer_loading.integer)
3863                         Con_Printf("loading cubemap \"%s\"\n", basename);
3864
3865                 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);
3866                 Mem_Free(cubemappixels);
3867         }
3868         else
3869         {
3870                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3871                 if (developer_loading.integer)
3872                 {
3873                         Con_Printf("(tried tried images ");
3874                         for (j = 0;j < 3;j++)
3875                                 for (i = 0;i < 6;i++)
3876                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3877                         Con_Print(" and was unable to find any of them).\n");
3878                 }
3879         }
3880         return cubemaptexture;
3881 }
3882
3883 rtexture_t *R_GetCubemap(const char *basename)
3884 {
3885         int i;
3886         for (i = 0;i < r_texture_numcubemaps;i++)
3887                 if (r_texture_cubemaps[i] != NULL)
3888                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3889                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3890         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3891                 return r_texture_whitecube;
3892         r_texture_numcubemaps++;
3893         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3894         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3895         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3896         return r_texture_cubemaps[i]->texture;
3897 }
3898
3899 static void R_Main_FreeViewCache(void)
3900 {
3901         if (r_refdef.viewcache.entityvisible)
3902                 Mem_Free(r_refdef.viewcache.entityvisible);
3903         if (r_refdef.viewcache.world_pvsbits)
3904                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3905         if (r_refdef.viewcache.world_leafvisible)
3906                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3907         if (r_refdef.viewcache.world_surfacevisible)
3908                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3909         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3910 }
3911
3912 static void R_Main_ResizeViewCache(void)
3913 {
3914         int numentities = r_refdef.scene.numentities;
3915         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3916         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3917         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3918         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3919         if (r_refdef.viewcache.maxentities < numentities)
3920         {
3921                 r_refdef.viewcache.maxentities = numentities;
3922                 if (r_refdef.viewcache.entityvisible)
3923                         Mem_Free(r_refdef.viewcache.entityvisible);
3924                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3925         }
3926         if (r_refdef.viewcache.world_numclusters != numclusters)
3927         {
3928                 r_refdef.viewcache.world_numclusters = numclusters;
3929                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3930                 if (r_refdef.viewcache.world_pvsbits)
3931                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3932                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3933         }
3934         if (r_refdef.viewcache.world_numleafs != numleafs)
3935         {
3936                 r_refdef.viewcache.world_numleafs = numleafs;
3937                 if (r_refdef.viewcache.world_leafvisible)
3938                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3939                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3940         }
3941         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3942         {
3943                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3944                 if (r_refdef.viewcache.world_surfacevisible)
3945                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3946                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3947         }
3948 }
3949
3950 extern rtexture_t *loadingscreentexture;
3951 static void gl_main_start(void)
3952 {
3953         loadingscreentexture = NULL;
3954         r_texture_blanknormalmap = NULL;
3955         r_texture_white = NULL;
3956         r_texture_grey128 = NULL;
3957         r_texture_black = NULL;
3958         r_texture_whitecube = NULL;
3959         r_texture_normalizationcube = NULL;
3960         r_texture_fogattenuation = NULL;
3961         r_texture_fogheighttexture = NULL;
3962         r_texture_gammaramps = NULL;
3963         r_texture_numcubemaps = 0;
3964
3965         r_loaddds = r_texture_dds_load.integer != 0;
3966         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3967
3968         switch(vid.renderpath)
3969         {
3970         case RENDERPATH_GL20:
3971         case RENDERPATH_D3D9:
3972         case RENDERPATH_D3D10:
3973         case RENDERPATH_D3D11:
3974         case RENDERPATH_SOFT:
3975         case RENDERPATH_GLES2:
3976                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3977                 Cvar_SetValueQuick(&gl_combine, 1);
3978                 Cvar_SetValueQuick(&r_glsl, 1);
3979                 r_loadnormalmap = true;
3980                 r_loadgloss = true;
3981                 r_loadfog = false;
3982                 break;
3983         case RENDERPATH_GL13:
3984         case RENDERPATH_GLES1:
3985                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3986                 Cvar_SetValueQuick(&gl_combine, 1);
3987                 Cvar_SetValueQuick(&r_glsl, 0);
3988                 r_loadnormalmap = false;
3989                 r_loadgloss = false;
3990                 r_loadfog = true;
3991                 break;
3992         case RENDERPATH_GL11:
3993                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3994                 Cvar_SetValueQuick(&gl_combine, 0);
3995                 Cvar_SetValueQuick(&r_glsl, 0);
3996                 r_loadnormalmap = false;
3997                 r_loadgloss = false;
3998                 r_loadfog = true;
3999                 break;
4000         }
4001
4002         R_AnimCache_Free();
4003         R_FrameData_Reset();
4004
4005         r_numqueries = 0;
4006         r_maxqueries = 0;
4007         memset(r_queries, 0, sizeof(r_queries));
4008
4009         r_qwskincache = NULL;
4010         r_qwskincache_size = 0;
4011
4012         // due to caching of texture_t references, the collision cache must be reset
4013         Collision_Cache_Reset(true);
4014
4015         // set up r_skinframe loading system for textures
4016         memset(&r_skinframe, 0, sizeof(r_skinframe));
4017         r_skinframe.loadsequence = 1;
4018         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4019
4020         r_main_texturepool = R_AllocTexturePool();
4021         R_BuildBlankTextures();
4022         R_BuildNoTexture();
4023         if (vid.support.arb_texture_cube_map)
4024         {
4025                 R_BuildWhiteCube();
4026                 R_BuildNormalizationCube();
4027         }
4028         r_texture_fogattenuation = NULL;
4029         r_texture_fogheighttexture = NULL;
4030         r_texture_gammaramps = NULL;
4031         //r_texture_fogintensity = NULL;
4032         memset(&r_fb, 0, sizeof(r_fb));
4033         r_glsl_permutation = NULL;
4034         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4035         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4036         glslshaderstring = NULL;
4037 #ifdef SUPPORTD3D
4038         r_hlsl_permutation = NULL;
4039         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4040         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4041 #endif
4042         hlslshaderstring = NULL;
4043         memset(&r_svbsp, 0, sizeof (r_svbsp));
4044
4045         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4046         r_texture_numcubemaps = 0;
4047
4048         r_refdef.fogmasktable_density = 0;
4049 }
4050
4051 static void gl_main_shutdown(void)
4052 {
4053         R_AnimCache_Free();
4054         R_FrameData_Reset();
4055
4056         R_Main_FreeViewCache();
4057
4058         switch(vid.renderpath)
4059         {
4060         case RENDERPATH_GL11:
4061         case RENDERPATH_GL13:
4062         case RENDERPATH_GL20:
4063         case RENDERPATH_GLES1:
4064         case RENDERPATH_GLES2:
4065 #ifdef GL_SAMPLES_PASSED_ARB
4066                 if (r_maxqueries)
4067                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4068 #endif
4069                 break;
4070         case RENDERPATH_D3D9:
4071                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4072                 break;
4073         case RENDERPATH_D3D10:
4074                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4075                 break;
4076         case RENDERPATH_D3D11:
4077                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4078                 break;
4079         case RENDERPATH_SOFT:
4080                 break;
4081         }
4082
4083         r_numqueries = 0;
4084         r_maxqueries = 0;
4085         memset(r_queries, 0, sizeof(r_queries));
4086
4087         r_qwskincache = NULL;
4088         r_qwskincache_size = 0;
4089
4090         // clear out the r_skinframe state
4091         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4092         memset(&r_skinframe, 0, sizeof(r_skinframe));
4093
4094         if (r_svbsp.nodes)
4095                 Mem_Free(r_svbsp.nodes);
4096         memset(&r_svbsp, 0, sizeof (r_svbsp));
4097         R_FreeTexturePool(&r_main_texturepool);
4098         loadingscreentexture = NULL;
4099         r_texture_blanknormalmap = NULL;
4100         r_texture_white = NULL;
4101         r_texture_grey128 = NULL;
4102         r_texture_black = NULL;
4103         r_texture_whitecube = NULL;
4104         r_texture_normalizationcube = NULL;
4105         r_texture_fogattenuation = NULL;
4106         r_texture_fogheighttexture = NULL;
4107         r_texture_gammaramps = NULL;
4108         r_texture_numcubemaps = 0;
4109         //r_texture_fogintensity = NULL;
4110         memset(&r_fb, 0, sizeof(r_fb));
4111         R_GLSL_Restart_f();
4112
4113         r_glsl_permutation = NULL;
4114         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4115         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4116         glslshaderstring = NULL;
4117 #ifdef SUPPORTD3D
4118         r_hlsl_permutation = NULL;
4119         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4120         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4121 #endif
4122         hlslshaderstring = NULL;
4123 }
4124
4125 static void gl_main_newmap(void)
4126 {
4127         // FIXME: move this code to client
4128         char *entities, entname[MAX_QPATH];
4129         if (r_qwskincache)
4130                 Mem_Free(r_qwskincache);
4131         r_qwskincache = NULL;
4132         r_qwskincache_size = 0;
4133         if (cl.worldmodel)
4134         {
4135                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4136                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4137                 {
4138                         CL_ParseEntityLump(entities);
4139                         Mem_Free(entities);
4140                         return;
4141                 }
4142                 if (cl.worldmodel->brush.entities)
4143                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4144         }
4145         R_Main_FreeViewCache();
4146
4147         R_FrameData_Reset();
4148 }
4149
4150 void GL_Main_Init(void)
4151 {
4152         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4153
4154         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4155         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4156         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4157         if (gamemode == GAME_NEHAHRA)
4158         {
4159                 Cvar_RegisterVariable (&gl_fogenable);
4160                 Cvar_RegisterVariable (&gl_fogdensity);
4161                 Cvar_RegisterVariable (&gl_fogred);
4162                 Cvar_RegisterVariable (&gl_foggreen);
4163                 Cvar_RegisterVariable (&gl_fogblue);
4164                 Cvar_RegisterVariable (&gl_fogstart);
4165                 Cvar_RegisterVariable (&gl_fogend);
4166                 Cvar_RegisterVariable (&gl_skyclip);
4167         }
4168         Cvar_RegisterVariable(&r_motionblur);
4169         Cvar_RegisterVariable(&r_damageblur);
4170         Cvar_RegisterVariable(&r_motionblur_averaging);
4171         Cvar_RegisterVariable(&r_motionblur_randomize);
4172         Cvar_RegisterVariable(&r_motionblur_minblur);
4173         Cvar_RegisterVariable(&r_motionblur_maxblur);
4174         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4175         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4176         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4177         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4178         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4179         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4180         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4181         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4182         Cvar_RegisterVariable(&r_equalize_entities_by);
4183         Cvar_RegisterVariable(&r_equalize_entities_to);
4184         Cvar_RegisterVariable(&r_depthfirst);
4185         Cvar_RegisterVariable(&r_useinfinitefarclip);
4186         Cvar_RegisterVariable(&r_farclip_base);
4187         Cvar_RegisterVariable(&r_farclip_world);
4188         Cvar_RegisterVariable(&r_nearclip);
4189         Cvar_RegisterVariable(&r_deformvertexes);
4190         Cvar_RegisterVariable(&r_transparent);
4191         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4192         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4193         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4194         Cvar_RegisterVariable(&r_showoverdraw);
4195         Cvar_RegisterVariable(&r_showbboxes);
4196         Cvar_RegisterVariable(&r_showsurfaces);
4197         Cvar_RegisterVariable(&r_showtris);
4198         Cvar_RegisterVariable(&r_shownormals);
4199         Cvar_RegisterVariable(&r_showlighting);
4200         Cvar_RegisterVariable(&r_showshadowvolumes);
4201         Cvar_RegisterVariable(&r_showcollisionbrushes);
4202         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4203         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4204         Cvar_RegisterVariable(&r_showdisabledepthtest);
4205         Cvar_RegisterVariable(&r_drawportals);
4206         Cvar_RegisterVariable(&r_drawentities);
4207         Cvar_RegisterVariable(&r_draw2d);
4208         Cvar_RegisterVariable(&r_drawworld);
4209         Cvar_RegisterVariable(&r_cullentities_trace);
4210         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4211         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4212         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4213         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4214         Cvar_RegisterVariable(&r_sortentities);
4215         Cvar_RegisterVariable(&r_drawviewmodel);
4216         Cvar_RegisterVariable(&r_drawexteriormodel);
4217         Cvar_RegisterVariable(&r_speeds);
4218         Cvar_RegisterVariable(&r_fullbrights);
4219         Cvar_RegisterVariable(&r_wateralpha);
4220         Cvar_RegisterVariable(&r_dynamic);
4221         Cvar_RegisterVariable(&r_fakelight);
4222         Cvar_RegisterVariable(&r_fakelight_intensity);
4223         Cvar_RegisterVariable(&r_fullbright);
4224         Cvar_RegisterVariable(&r_shadows);
4225         Cvar_RegisterVariable(&r_shadows_darken);
4226         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4227         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4228         Cvar_RegisterVariable(&r_shadows_throwdistance);
4229         Cvar_RegisterVariable(&r_shadows_throwdirection);
4230         Cvar_RegisterVariable(&r_shadows_focus);
4231         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4232         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4233         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4234         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4235         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4236         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4237         Cvar_RegisterVariable(&r_fog_exp2);
4238         Cvar_RegisterVariable(&r_fog_clear);
4239         Cvar_RegisterVariable(&r_drawfog);
4240         Cvar_RegisterVariable(&r_transparentdepthmasking);
4241         Cvar_RegisterVariable(&r_transparent_sortmindist);
4242         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4243         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4244         Cvar_RegisterVariable(&r_texture_dds_load);
4245         Cvar_RegisterVariable(&r_texture_dds_save);
4246         Cvar_RegisterVariable(&r_textureunits);
4247         Cvar_RegisterVariable(&gl_combine);
4248         Cvar_RegisterVariable(&r_usedepthtextures);
4249         Cvar_RegisterVariable(&r_viewfbo);
4250         Cvar_RegisterVariable(&r_viewscale);
4251         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4252         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4253         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4254         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4255         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4256         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4257         Cvar_RegisterVariable(&r_glsl);
4258         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4259         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4260         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4261         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4262         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4263         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4264         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4265         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4266         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4267         Cvar_RegisterVariable(&r_glsl_postprocess);
4268         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4269         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4270         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4271         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4272         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4273         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4274         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4275         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4276         Cvar_RegisterVariable(&r_celshading);
4277         Cvar_RegisterVariable(&r_celoutlines);
4278
4279         Cvar_RegisterVariable(&r_water);
4280         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4281         Cvar_RegisterVariable(&r_water_clippingplanebias);
4282         Cvar_RegisterVariable(&r_water_refractdistort);
4283         Cvar_RegisterVariable(&r_water_reflectdistort);
4284         Cvar_RegisterVariable(&r_water_scissormode);
4285         Cvar_RegisterVariable(&r_water_lowquality);
4286         Cvar_RegisterVariable(&r_water_hideplayer);
4287         Cvar_RegisterVariable(&r_water_fbo);
4288
4289         Cvar_RegisterVariable(&r_lerpsprites);
4290         Cvar_RegisterVariable(&r_lerpmodels);
4291         Cvar_RegisterVariable(&r_lerplightstyles);
4292         Cvar_RegisterVariable(&r_waterscroll);
4293         Cvar_RegisterVariable(&r_bloom);
4294         Cvar_RegisterVariable(&r_bloom_colorscale);
4295         Cvar_RegisterVariable(&r_bloom_brighten);
4296         Cvar_RegisterVariable(&r_bloom_blur);
4297         Cvar_RegisterVariable(&r_bloom_resolution);
4298         Cvar_RegisterVariable(&r_bloom_colorexponent);
4299         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4300         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4301         Cvar_RegisterVariable(&r_hdr_glowintensity);
4302         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4303         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4304         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4305         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4306         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4307         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4308         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4309         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4310         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4311         Cvar_RegisterVariable(&developer_texturelogging);
4312         Cvar_RegisterVariable(&gl_lightmaps);
4313         Cvar_RegisterVariable(&r_test);
4314         Cvar_RegisterVariable(&r_glsl_saturation);
4315         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4316         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4317         Cvar_RegisterVariable(&r_framedatasize);
4318         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4319                 Cvar_SetValue("r_fullbrights", 0);
4320         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4321 }
4322
4323 void Render_Init(void)
4324 {
4325         gl_backend_init();
4326         R_Textures_Init();
4327         GL_Main_Init();
4328         Font_Init();
4329         GL_Draw_Init();
4330         R_Shadow_Init();
4331         R_Sky_Init();
4332         GL_Surf_Init();
4333         Sbar_Init();
4334         R_Particles_Init();
4335         R_Explosion_Init();
4336         R_LightningBeams_Init();
4337         Mod_RenderInit();
4338 }
4339
4340 /*
4341 ===============
4342 GL_Init
4343 ===============
4344 */
4345 #ifndef USE_GLES2
4346 extern char *ENGINE_EXTENSIONS;
4347 void GL_Init (void)
4348 {
4349         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4350         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4351         gl_version = (const char *)qglGetString(GL_VERSION);
4352         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4353
4354         if (!gl_extensions)
4355                 gl_extensions = "";
4356         if (!gl_platformextensions)
4357                 gl_platformextensions = "";
4358
4359         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4360         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4361         Con_Printf("GL_VERSION: %s\n", gl_version);
4362         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4363         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4364
4365         VID_CheckExtensions();
4366
4367         // LordHavoc: report supported extensions
4368         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4369
4370         // clear to black (loading plaque will be seen over this)
4371         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4372 }
4373 #endif
4374
4375 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4376 {
4377         int i;
4378         mplane_t *p;
4379         if (r_trippy.integer)
4380                 return false;
4381         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4382         {
4383                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4384                 if (i == 4)
4385                         continue;
4386                 p = r_refdef.view.frustum + i;
4387                 switch(p->signbits)
4388                 {
4389                 default:
4390                 case 0:
4391                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4392                                 return true;
4393                         break;
4394                 case 1:
4395                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4396                                 return true;
4397                         break;
4398                 case 2:
4399                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4400                                 return true;
4401                         break;
4402                 case 3:
4403                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4404                                 return true;
4405                         break;
4406                 case 4:
4407                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4408                                 return true;
4409                         break;
4410                 case 5:
4411                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4412                                 return true;
4413                         break;
4414                 case 6:
4415                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4416                                 return true;
4417                         break;
4418                 case 7:
4419                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4420                                 return true;
4421                         break;
4422                 }
4423         }
4424         return false;
4425 }
4426
4427 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4428 {
4429         int i;
4430         const mplane_t *p;
4431         if (r_trippy.integer)
4432                 return false;
4433         for (i = 0;i < numplanes;i++)
4434         {
4435                 p = planes + i;
4436                 switch(p->signbits)
4437                 {
4438                 default:
4439                 case 0:
4440                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4441                                 return true;
4442                         break;
4443                 case 1:
4444                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 case 2:
4448                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4449                                 return true;
4450                         break;
4451                 case 3:
4452                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4453                                 return true;
4454                         break;
4455                 case 4:
4456                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4457                                 return true;
4458                         break;
4459                 case 5:
4460                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4461                                 return true;
4462                         break;
4463                 case 6:
4464                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4465                                 return true;
4466                         break;
4467                 case 7:
4468                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4469                                 return true;
4470                         break;
4471                 }
4472         }
4473         return false;
4474 }
4475
4476 //==================================================================================
4477
4478 // LordHavoc: this stores temporary data used within the same frame
4479
4480 typedef struct r_framedata_mem_s
4481 {
4482         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4483         size_t size; // how much usable space
4484         size_t current; // how much space in use
4485         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4486         size_t wantedsize; // how much space was allocated
4487         unsigned char *data; // start of real data (16byte aligned)
4488 }
4489 r_framedata_mem_t;
4490
4491 static r_framedata_mem_t *r_framedata_mem;
4492
4493 void R_FrameData_Reset(void)
4494 {
4495         while (r_framedata_mem)
4496         {
4497                 r_framedata_mem_t *next = r_framedata_mem->purge;
4498                 Mem_Free(r_framedata_mem);
4499                 r_framedata_mem = next;
4500         }
4501 }
4502
4503 static void R_FrameData_Resize(void)
4504 {
4505         size_t wantedsize;
4506         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4507         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4508         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4509         {
4510                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4511                 newmem->wantedsize = wantedsize;
4512                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4513                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4514                 newmem->current = 0;
4515                 newmem->mark = 0;
4516                 newmem->purge = r_framedata_mem;
4517                 r_framedata_mem = newmem;
4518         }
4519 }
4520
4521 void R_FrameData_NewFrame(void)
4522 {
4523         R_FrameData_Resize();
4524         if (!r_framedata_mem)
4525                 return;
4526         // if we ran out of space on the last frame, free the old memory now
4527         while (r_framedata_mem->purge)
4528         {
4529                 // repeatedly remove the second item in the list, leaving only head
4530                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4531                 Mem_Free(r_framedata_mem->purge);
4532                 r_framedata_mem->purge = next;
4533         }
4534         // reset the current mem pointer
4535         r_framedata_mem->current = 0;
4536         r_framedata_mem->mark = 0;
4537 }
4538
4539 void *R_FrameData_Alloc(size_t size)
4540 {
4541         void *data;
4542
4543         // align to 16 byte boundary - the data pointer is already aligned, so we
4544         // only need to ensure the size of every allocation is also aligned
4545         size = (size + 15) & ~15;
4546
4547         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4548         {
4549                 // emergency - we ran out of space, allocate more memory
4550                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4551                 R_FrameData_Resize();
4552         }
4553
4554         data = r_framedata_mem->data + r_framedata_mem->current;
4555         r_framedata_mem->current += size;
4556
4557         // count the usage for stats
4558         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4559         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4560
4561         return (void *)data;
4562 }
4563
4564 void *R_FrameData_Store(size_t size, void *data)
4565 {
4566         void *d = R_FrameData_Alloc(size);
4567         if (d && data)
4568                 memcpy(d, data, size);
4569         return d;
4570 }
4571
4572 void R_FrameData_SetMark(void)
4573 {
4574         if (!r_framedata_mem)
4575                 return;
4576         r_framedata_mem->mark = r_framedata_mem->current;
4577 }
4578
4579 void R_FrameData_ReturnToMark(void)
4580 {
4581         if (!r_framedata_mem)
4582                 return;
4583         r_framedata_mem->current = r_framedata_mem->mark;
4584 }
4585
4586 //==================================================================================
4587
4588 // LordHavoc: animcache originally written by Echon, rewritten since then
4589
4590 /**
4591  * Animation cache prevents re-generating mesh data for an animated model
4592  * multiple times in one frame for lighting, shadowing, reflections, etc.
4593  */
4594
4595 void R_AnimCache_Free(void)
4596 {
4597 }
4598
4599 void R_AnimCache_ClearCache(void)
4600 {
4601         int i;
4602         entity_render_t *ent;
4603
4604         for (i = 0;i < r_refdef.scene.numentities;i++)
4605         {
4606                 ent = r_refdef.scene.entities[i];
4607                 ent->animcache_vertex3f = NULL;
4608                 ent->animcache_normal3f = NULL;
4609                 ent->animcache_svector3f = NULL;
4610                 ent->animcache_tvector3f = NULL;
4611                 ent->animcache_vertexmesh = NULL;
4612                 ent->animcache_vertex3fbuffer = NULL;
4613                 ent->animcache_vertexmeshbuffer = NULL;
4614         }
4615 }
4616
4617 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4618 {
4619         int i;
4620
4621         // check if we need the meshbuffers
4622         if (!vid.useinterleavedarrays)
4623                 return;
4624
4625         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4626                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4627         // TODO: upload vertex3f buffer?
4628         if (ent->animcache_vertexmesh)
4629         {
4630                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4631                 for (i = 0;i < numvertices;i++)
4632                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4633                 if (ent->animcache_svector3f)
4634                         for (i = 0;i < numvertices;i++)
4635                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4636                 if (ent->animcache_tvector3f)
4637                         for (i = 0;i < numvertices;i++)
4638                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4639                 if (ent->animcache_normal3f)
4640                         for (i = 0;i < numvertices;i++)
4641                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4642                 // TODO: upload vertexmeshbuffer?
4643         }
4644 }
4645
4646 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4647 {
4648         dp_model_t *model = ent->model;
4649         int numvertices;
4650         // see if it's already cached this frame
4651         if (ent->animcache_vertex3f)
4652         {
4653                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4654                 if (wantnormals || wanttangents)
4655                 {
4656                         if (ent->animcache_normal3f)
4657                                 wantnormals = false;
4658                         if (ent->animcache_svector3f)
4659                                 wanttangents = false;
4660                         if (wantnormals || wanttangents)
4661                         {
4662                                 numvertices = model->surfmesh.num_vertices;
4663                                 if (wantnormals)
4664                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4665                                 if (wanttangents)
4666                                 {
4667                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4668                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4669                                 }
4670                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4671                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4672                         }
4673                 }
4674         }
4675         else
4676         {
4677                 // see if this ent is worth caching
4678                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4679                         return false;
4680                 // get some memory for this entity and generate mesh data
4681                 numvertices = model->surfmesh.num_vertices;
4682                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4683                 if (wantnormals)
4684                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4685                 if (wanttangents)
4686                 {
4687                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4688                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4689                 }
4690                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4691                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4692         }
4693         return true;
4694 }
4695
4696 void R_AnimCache_CacheVisibleEntities(void)
4697 {
4698         int i;
4699         qboolean wantnormals = true;
4700         qboolean wanttangents = !r_showsurfaces.integer;
4701
4702         switch(vid.renderpath)
4703         {
4704         case RENDERPATH_GL20:
4705         case RENDERPATH_D3D9:
4706         case RENDERPATH_D3D10:
4707         case RENDERPATH_D3D11:
4708         case RENDERPATH_GLES2:
4709                 break;
4710         case RENDERPATH_GL11:
4711         case RENDERPATH_GL13:
4712         case RENDERPATH_GLES1:
4713                 wanttangents = false;
4714                 break;
4715         case RENDERPATH_SOFT:
4716                 break;
4717         }
4718
4719         if (r_shownormals.integer)
4720                 wanttangents = wantnormals = true;
4721
4722         // TODO: thread this
4723         // NOTE: R_PrepareRTLights() also caches entities
4724
4725         for (i = 0;i < r_refdef.scene.numentities;i++)
4726                 if (r_refdef.viewcache.entityvisible[i])
4727                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4728 }
4729
4730 //==================================================================================
4731
4732 extern cvar_t r_overheadsprites_pushback;
4733
4734 static void R_View_UpdateEntityLighting (void)
4735 {
4736         int i;
4737         entity_render_t *ent;
4738         vec3_t tempdiffusenormal, avg;
4739         vec_t f, fa, fd, fdd;
4740         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4741
4742         for (i = 0;i < r_refdef.scene.numentities;i++)
4743         {
4744                 ent = r_refdef.scene.entities[i];
4745
4746                 // skip unseen models
4747                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen))
4748                         continue;
4749
4750                 // skip bsp models
4751                 if (ent->model && ent->model == cl.worldmodel)
4752                 {
4753                         // TODO: use modellight for r_ambient settings on world?
4754                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4755                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4756                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4757                         continue;
4758                 }
4759                 
4760                 if (ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4761                 {
4762                         // aleady updated by CSQC
4763                         // TODO: force modellight on BSP models in this case?
4764                         VectorCopy(ent->modellight_lightdir, tempdiffusenormal); 
4765                 }
4766                 else
4767                 {
4768                         // fetch the lighting from the worldmodel data
4769                         VectorClear(ent->modellight_ambient);
4770                         VectorClear(ent->modellight_diffuse);
4771                         VectorClear(tempdiffusenormal);
4772                         if (ent->flags & RENDER_LIGHT)
4773                         {
4774                                 vec3_t org;
4775                                 Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4776
4777                                 // complete lightning for lit sprites
4778                                 // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4779                                 if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4780                                 {
4781                                         if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4782                                                 org[2] = org[2] + r_overheadsprites_pushback.value;
4783                                         R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4784                                 }
4785                                 else
4786                                         R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4787
4788                                 if(ent->flags & RENDER_EQUALIZE)
4789                                 {
4790                                         // first fix up ambient lighting...
4791                                         if(r_equalize_entities_minambient.value > 0)
4792                                         {
4793                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4794                                                 if(fd > 0)
4795                                                 {
4796                                                         fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4797                                                         if(fa < r_equalize_entities_minambient.value * fd)
4798                                                         {
4799                                                                 // solve:
4800                                                                 //   fa'/fd' = minambient
4801                                                                 //   fa'+0.25*fd' = fa+0.25*fd
4802                                                                 //   ...
4803                                                                 //   fa' = fd' * minambient
4804                                                                 //   fd'*(0.25+minambient) = fa+0.25*fd
4805                                                                 //   ...
4806                                                                 //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4807                                                                 //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4808                                                                 //   ...
4809                                                                 fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4810                                                                 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
4811                                                                 VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4812                                                                 VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4813                                                         }
4814                                                 }
4815                                         }
4816
4817                                         if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4818                                         {
4819                                                 fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4820                                                 fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4821                                                 f = fa + 0.25 * fd;
4822                                                 if(f > 0)
4823                                                 {
4824                                                         // adjust brightness and saturation to target
4825                                                         avg[0] = avg[1] = avg[2] = fa / f;
4826                                                         VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4827                                                         avg[0] = avg[1] = avg[2] = fd / f;
4828                                                         VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4829                                                 }
4830                                         }
4831                                 }
4832                         }
4833                         else // highly rare
4834                                 VectorSet(ent->modellight_ambient, 1, 1, 1);
4835                 }
4836
4837                 // move the light direction into modelspace coordinates for lighting code
4838                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4839                 if(VectorLength2(ent->modellight_lightdir) == 0)
4840                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4841                 VectorNormalize(ent->modellight_lightdir);
4842         }
4843 }
4844
4845 #define MAX_LINEOFSIGHTTRACES 64
4846
4847 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4848 {
4849         int i;
4850         vec3_t boxmins, boxmaxs;
4851         vec3_t start;
4852         vec3_t end;
4853         dp_model_t *model = r_refdef.scene.worldmodel;
4854
4855         if (!model || !model->brush.TraceLineOfSight)
4856                 return true;
4857
4858         // expand the box a little
4859         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4860         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4861         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4862         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4863         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4864         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4865
4866         // return true if eye is inside enlarged box
4867         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4868                 return true;
4869
4870         // try center
4871         VectorCopy(eye, start);
4872         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4873         if (model->brush.TraceLineOfSight(model, start, end))
4874                 return true;
4875
4876         // try various random positions
4877         for (i = 0;i < numsamples;i++)
4878         {
4879                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4880                 if (model->brush.TraceLineOfSight(model, start, end))
4881                         return true;
4882         }
4883
4884         return false;
4885 }
4886
4887
4888 static void R_View_UpdateEntityVisible (void)
4889 {
4890         int i;
4891         int renderimask;
4892         int samples;
4893         entity_render_t *ent;
4894
4895         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4896                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4897                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4898                 :                                                          RENDER_EXTERIORMODEL;
4899         if (!r_drawviewmodel.integer)
4900                 renderimask |= RENDER_VIEWMODEL;
4901         if (!r_drawexteriormodel.integer)
4902                 renderimask |= RENDER_EXTERIORMODEL;
4903         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4904         {
4905                 // worldmodel can check visibility
4906                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4907                 for (i = 0;i < r_refdef.scene.numentities;i++)
4908                 {
4909                         ent = r_refdef.scene.entities[i];
4910                         if (!(ent->flags & renderimask))
4911                         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)))
4912                         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))
4913                                 r_refdef.viewcache.entityvisible[i] = true;
4914                 }
4915         }
4916         else
4917         {
4918                 // no worldmodel or it can't check visibility
4919                 for (i = 0;i < r_refdef.scene.numentities;i++)
4920                 {
4921                         ent = r_refdef.scene.entities[i];
4922                         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));
4923                 }
4924         }
4925         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4926                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4927         {
4928                 for (i = 0;i < r_refdef.scene.numentities;i++)
4929                 {
4930                         if (!r_refdef.viewcache.entityvisible[i])
4931                                 continue;
4932                         ent = r_refdef.scene.entities[i];
4933                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4934                         {
4935                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4936                                 if (samples < 0)
4937                                         continue; // temp entities do pvs only
4938                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4939                                         ent->last_trace_visibility = realtime;
4940                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4941                                         r_refdef.viewcache.entityvisible[i] = 0;
4942                         }
4943                 }
4944         }
4945 }
4946
4947 /// only used if skyrendermasked, and normally returns false
4948 static int R_DrawBrushModelsSky (void)
4949 {
4950         int i, sky;
4951         entity_render_t *ent;
4952
4953         sky = false;
4954         for (i = 0;i < r_refdef.scene.numentities;i++)
4955         {
4956                 if (!r_refdef.viewcache.entityvisible[i])
4957                         continue;
4958                 ent = r_refdef.scene.entities[i];
4959                 if (!ent->model || !ent->model->DrawSky)
4960                         continue;
4961                 ent->model->DrawSky(ent);
4962                 sky = true;
4963         }
4964         return sky;
4965 }
4966
4967 static void R_DrawNoModel(entity_render_t *ent);
4968 static void R_DrawModels(void)
4969 {
4970         int i;
4971         entity_render_t *ent;
4972
4973         for (i = 0;i < r_refdef.scene.numentities;i++)
4974         {
4975                 if (!r_refdef.viewcache.entityvisible[i])
4976                         continue;
4977                 ent = r_refdef.scene.entities[i];
4978                 r_refdef.stats.entities++;
4979                 /*
4980                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4981                 {
4982                         vec3_t f, l, u, o;
4983                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4984                         Con_Printf("R_DrawModels\n");
4985                         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]);
4986                         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);
4987                         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);
4988                 }
4989                 */
4990                 if (ent->model && ent->model->Draw != NULL)
4991                         ent->model->Draw(ent);
4992                 else
4993                         R_DrawNoModel(ent);
4994         }
4995 }
4996
4997 static void R_DrawModelsDepth(void)
4998 {
4999         int i;
5000         entity_render_t *ent;
5001
5002         for (i = 0;i < r_refdef.scene.numentities;i++)
5003         {
5004                 if (!r_refdef.viewcache.entityvisible[i])
5005                         continue;
5006                 ent = r_refdef.scene.entities[i];
5007                 if (ent->model && ent->model->DrawDepth != NULL)
5008                         ent->model->DrawDepth(ent);
5009         }
5010 }
5011
5012 static void R_DrawModelsDebug(void)
5013 {
5014         int i;
5015         entity_render_t *ent;
5016
5017         for (i = 0;i < r_refdef.scene.numentities;i++)
5018         {
5019                 if (!r_refdef.viewcache.entityvisible[i])
5020                         continue;
5021                 ent = r_refdef.scene.entities[i];
5022                 if (ent->model && ent->model->DrawDebug != NULL)
5023                         ent->model->DrawDebug(ent);
5024         }
5025 }
5026
5027 static void R_DrawModelsAddWaterPlanes(void)
5028 {
5029         int i;
5030         entity_render_t *ent;
5031
5032         for (i = 0;i < r_refdef.scene.numentities;i++)
5033         {
5034                 if (!r_refdef.viewcache.entityvisible[i])
5035                         continue;
5036                 ent = r_refdef.scene.entities[i];
5037                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5038                         ent->model->DrawAddWaterPlanes(ent);
5039         }
5040 }
5041
5042 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}};
5043
5044 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5045 {
5046         if (r_hdr_irisadaptation.integer)
5047         {
5048                 vec3_t p;
5049                 vec3_t ambient;
5050                 vec3_t diffuse;
5051                 vec3_t diffusenormal;
5052                 vec3_t forward;
5053                 vec_t brightness = 0.0f;
5054                 vec_t goal;
5055                 vec_t current;
5056                 vec_t d;
5057                 int c;
5058                 VectorCopy(r_refdef.view.forward, forward);
5059                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5060                 {
5061                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5062                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5063                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5064                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5065                         d = DotProduct(forward, diffusenormal);
5066                         brightness += VectorLength(ambient);
5067                         if (d > 0)
5068                                 brightness += d * VectorLength(diffuse);
5069                 }
5070                 brightness *= 1.0f / c;
5071                 brightness += 0.00001f; // make sure it's never zero
5072                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5073                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5074                 current = r_hdr_irisadaptation_value.value;
5075                 if (current < goal)
5076                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5077                 else if (current > goal)
5078                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5079                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5080                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5081         }
5082         else if (r_hdr_irisadaptation_value.value != 1.0f)
5083                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5084 }
5085
5086 static void R_View_SetFrustum(const int *scissor)
5087 {
5088         int i;
5089         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5090         vec3_t forward, left, up, origin, v;
5091
5092         if(scissor)
5093         {
5094                 // flipped x coordinates (because x points left here)
5095                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5096                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5097
5098                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5099                 switch(vid.renderpath)
5100                 {
5101                         case RENDERPATH_D3D9:
5102                         case RENDERPATH_D3D10:
5103                         case RENDERPATH_D3D11:
5104                                 // non-flipped y coordinates
5105                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5106                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5107                                 break;
5108                         case RENDERPATH_SOFT:
5109                         case RENDERPATH_GL11:
5110                         case RENDERPATH_GL13:
5111                         case RENDERPATH_GL20:
5112                         case RENDERPATH_GLES1:
5113                         case RENDERPATH_GLES2:
5114                                 // non-flipped y coordinates
5115                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5116                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5117                                 break;
5118                 }
5119         }
5120
5121         // we can't trust r_refdef.view.forward and friends in reflected scenes
5122         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5123
5124 #if 0
5125         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5126         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5127         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5128         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5129         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5130         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5131         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5132         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5133         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5134         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5135         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5136         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5137 #endif
5138
5139 #if 0
5140         zNear = r_refdef.nearclip;
5141         nudge = 1.0 - 1.0 / (1<<23);
5142         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5143         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5144         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5145         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5146         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5147         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5148         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5149         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5150 #endif
5151
5152
5153
5154 #if 0
5155         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5156         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5157         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5158         r_refdef.view.frustum[0].dist = m[15] - m[12];
5159
5160         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5161         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5162         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5163         r_refdef.view.frustum[1].dist = m[15] + m[12];
5164
5165         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5166         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5167         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5168         r_refdef.view.frustum[2].dist = m[15] - m[13];
5169
5170         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5171         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5172         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5173         r_refdef.view.frustum[3].dist = m[15] + m[13];
5174
5175         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5176         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5177         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5178         r_refdef.view.frustum[4].dist = m[15] - m[14];
5179
5180         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5181         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5182         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5183         r_refdef.view.frustum[5].dist = m[15] + m[14];
5184 #endif
5185
5186         if (r_refdef.view.useperspective)
5187         {
5188                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5189                 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]);
5190                 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]);
5191                 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]);
5192                 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]);
5193
5194                 // then the normals from the corners relative to origin
5195                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5196                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5197                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5198                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5199
5200                 // in a NORMAL view, forward cross left == up
5201                 // in a REFLECTED view, forward cross left == down
5202                 // so our cross products above need to be adjusted for a left handed coordinate system
5203                 CrossProduct(forward, left, v);
5204                 if(DotProduct(v, up) < 0)
5205                 {
5206                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5207                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5208                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5209                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5210                 }
5211
5212                 // Leaving those out was a mistake, those were in the old code, and they
5213                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5214                 // I couldn't reproduce it after adding those normalizations. --blub
5215                 VectorNormalize(r_refdef.view.frustum[0].normal);
5216                 VectorNormalize(r_refdef.view.frustum[1].normal);
5217                 VectorNormalize(r_refdef.view.frustum[2].normal);
5218                 VectorNormalize(r_refdef.view.frustum[3].normal);
5219
5220                 // make the corners absolute
5221                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5222                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5223                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5224                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5225
5226                 // one more normal
5227                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5228
5229                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5230                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5231                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5232                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5233                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5234         }
5235         else
5236         {
5237                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5238                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5239                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5240                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5241                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5242                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5243                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5244                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5245                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5246                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5247         }
5248         r_refdef.view.numfrustumplanes = 5;
5249
5250         if (r_refdef.view.useclipplane)
5251         {
5252                 r_refdef.view.numfrustumplanes = 6;
5253                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5254         }
5255
5256         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5257                 PlaneClassify(r_refdef.view.frustum + i);
5258
5259         // LordHavoc: note to all quake engine coders, Quake had a special case
5260         // for 90 degrees which assumed a square view (wrong), so I removed it,
5261         // Quake2 has it disabled as well.
5262
5263         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5264         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5265         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5266         //PlaneClassify(&frustum[0]);
5267
5268         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5269         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5270         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5271         //PlaneClassify(&frustum[1]);
5272
5273         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5274         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5275         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5276         //PlaneClassify(&frustum[2]);
5277
5278         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5279         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5280         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5281         //PlaneClassify(&frustum[3]);
5282
5283         // nearclip plane
5284         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5285         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5286         //PlaneClassify(&frustum[4]);
5287 }
5288
5289 static void R_View_UpdateWithScissor(const int *myscissor)
5290 {
5291         R_Main_ResizeViewCache();
5292         R_View_SetFrustum(myscissor);
5293         R_View_WorldVisibility(r_refdef.view.useclipplane);
5294         R_View_UpdateEntityVisible();
5295         R_View_UpdateEntityLighting();
5296 }
5297
5298 static void R_View_Update(void)
5299 {
5300         R_Main_ResizeViewCache();
5301         R_View_SetFrustum(NULL);
5302         R_View_WorldVisibility(r_refdef.view.useclipplane);
5303         R_View_UpdateEntityVisible();
5304         R_View_UpdateEntityLighting();
5305 }
5306
5307 float viewscalefpsadjusted = 1.0f;
5308
5309 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5310 {
5311         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5312         scale = bound(0.03125f, scale, 1.0f);
5313         *outwidth = (int)ceil(width * scale);
5314         *outheight = (int)ceil(height * scale);
5315 }
5316
5317 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5318 {
5319         const float *customclipplane = NULL;
5320         float plane[4];
5321         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5322         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5323         {
5324                 // LordHavoc: couldn't figure out how to make this approach the
5325                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5326                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5327                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5328                         dist = r_refdef.view.clipplane.dist;
5329                 plane[0] = r_refdef.view.clipplane.normal[0];
5330                 plane[1] = r_refdef.view.clipplane.normal[1];
5331                 plane[2] = r_refdef.view.clipplane.normal[2];
5332                 plane[3] = -dist;
5333                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5334         }
5335
5336         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5337         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5338
5339         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5340         if (!r_refdef.view.useperspective)
5341                 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);
5342         else if (vid.stencil && r_useinfinitefarclip.integer)
5343                 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);
5344         else
5345                 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);
5346         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5347         R_SetViewport(&r_refdef.view.viewport);
5348         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5349         {
5350                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5351                 float screenplane[4];
5352                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5353                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5354                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5355                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5356                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5357         }
5358 }
5359
5360 void R_EntityMatrix(const matrix4x4_t *matrix)
5361 {
5362         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5363         {
5364                 gl_modelmatrixchanged = false;
5365                 gl_modelmatrix = *matrix;
5366                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5367                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5368                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5369                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5370                 CHECKGLERROR
5371                 switch(vid.renderpath)
5372                 {
5373                 case RENDERPATH_D3D9:
5374 #ifdef SUPPORTD3D
5375                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5376                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5377 #endif
5378                         break;
5379                 case RENDERPATH_D3D10:
5380                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5381                         break;
5382                 case RENDERPATH_D3D11:
5383                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5384                         break;
5385                 case RENDERPATH_GL11:
5386                 case RENDERPATH_GL13:
5387                 case RENDERPATH_GLES1:
5388                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5389                         break;
5390                 case RENDERPATH_SOFT:
5391                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5392                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5393                         break;
5394                 case RENDERPATH_GL20:
5395                 case RENDERPATH_GLES2:
5396                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5397                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5398                         break;
5399                 }
5400         }
5401 }
5402
5403 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5404 {
5405         r_viewport_t viewport;
5406
5407         CHECKGLERROR
5408
5409         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5410         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);
5411         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5412         R_SetViewport(&viewport);
5413         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5414         GL_Color(1, 1, 1, 1);
5415         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5416         GL_BlendFunc(GL_ONE, GL_ZERO);
5417         GL_ScissorTest(false);
5418         GL_DepthMask(false);
5419         GL_DepthRange(0, 1);
5420         GL_DepthTest(false);
5421         GL_DepthFunc(GL_LEQUAL);
5422         R_EntityMatrix(&identitymatrix);
5423         R_Mesh_ResetTextureState();
5424         GL_PolygonOffset(0, 0);
5425         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5426         switch(vid.renderpath)
5427         {
5428         case RENDERPATH_GL11:
5429         case RENDERPATH_GL13:
5430         case RENDERPATH_GL20:
5431         case RENDERPATH_GLES1:
5432         case RENDERPATH_GLES2:
5433                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5434                 break;
5435         case RENDERPATH_D3D9:
5436         case RENDERPATH_D3D10:
5437         case RENDERPATH_D3D11:
5438         case RENDERPATH_SOFT:
5439                 break;
5440         }
5441         GL_CullFace(GL_NONE);
5442
5443         CHECKGLERROR
5444 }
5445
5446 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5447 {
5448         DrawQ_Finish();
5449
5450         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5451 }
5452
5453 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5454 {
5455         DrawQ_Finish();
5456
5457         R_SetupView(true, fbo, depthtexture, colortexture);
5458         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5459         GL_Color(1, 1, 1, 1);
5460         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5461         GL_BlendFunc(GL_ONE, GL_ZERO);
5462         GL_ScissorTest(true);
5463         GL_DepthMask(true);
5464         GL_DepthRange(0, 1);
5465         GL_DepthTest(true);
5466         GL_DepthFunc(GL_LEQUAL);
5467         R_EntityMatrix(&identitymatrix);
5468         R_Mesh_ResetTextureState();
5469         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5470         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5471         switch(vid.renderpath)
5472         {
5473         case RENDERPATH_GL11:
5474         case RENDERPATH_GL13:
5475         case RENDERPATH_GL20:
5476         case RENDERPATH_GLES1:
5477         case RENDERPATH_GLES2:
5478                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5479                 break;
5480         case RENDERPATH_D3D9:
5481         case RENDERPATH_D3D10:
5482         case RENDERPATH_D3D11:
5483         case RENDERPATH_SOFT:
5484                 break;
5485         }
5486         GL_CullFace(r_refdef.view.cullface_back);
5487 }
5488
5489 /*
5490 ================
5491 R_RenderView_UpdateViewVectors
5492 ================
5493 */
5494 void R_RenderView_UpdateViewVectors(void)
5495 {
5496         // break apart the view matrix into vectors for various purposes
5497         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5498         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5499         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5500         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5501         // make an inverted copy of the view matrix for tracking sprites
5502         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5503 }
5504
5505 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5506 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5507
5508 static void R_Water_StartFrame(void)
5509 {
5510         int i;
5511         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5512         r_waterstate_waterplane_t *p;
5513         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5514
5515         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5516                 return;
5517
5518         switch(vid.renderpath)
5519         {
5520         case RENDERPATH_GL20:
5521         case RENDERPATH_D3D9:
5522         case RENDERPATH_D3D10:
5523         case RENDERPATH_D3D11:
5524         case RENDERPATH_SOFT:
5525         case RENDERPATH_GLES2:
5526                 break;
5527         case RENDERPATH_GL11:
5528         case RENDERPATH_GL13:
5529         case RENDERPATH_GLES1:
5530                 return;
5531         }
5532
5533         // set waterwidth and waterheight to the water resolution that will be
5534         // used (often less than the screen resolution for faster rendering)
5535         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5536
5537         // calculate desired texture sizes
5538         // can't use water if the card does not support the texture size
5539         if (!r_water.integer || r_showsurfaces.integer)
5540                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5541         else if (vid.support.arb_texture_non_power_of_two)
5542         {
5543                 texturewidth = waterwidth;
5544                 textureheight = waterheight;
5545                 camerawidth = waterwidth;
5546                 cameraheight = waterheight;
5547         }
5548         else
5549         {
5550                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5551                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5552                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5553                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5554         }
5555
5556         // allocate textures as needed
5557         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))
5558         {
5559                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5560                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5561                 {
5562                         if (p->texture_refraction)
5563                                 R_FreeTexture(p->texture_refraction);
5564                         p->texture_refraction = NULL;
5565                         if (p->fbo_refraction)
5566                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5567                         p->fbo_refraction = 0;
5568                         if (p->texture_reflection)
5569                                 R_FreeTexture(p->texture_reflection);
5570                         p->texture_reflection = NULL;
5571                         if (p->fbo_reflection)
5572                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5573                         p->fbo_reflection = 0;
5574                         if (p->texture_camera)
5575                                 R_FreeTexture(p->texture_camera);
5576                         p->texture_camera = NULL;
5577                         if (p->fbo_camera)
5578                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5579                         p->fbo_camera = 0;
5580                 }
5581                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5582                 r_fb.water.texturewidth = texturewidth;
5583                 r_fb.water.textureheight = textureheight;
5584                 r_fb.water.camerawidth = camerawidth;
5585                 r_fb.water.cameraheight = cameraheight;
5586         }
5587
5588         if (r_fb.water.texturewidth)
5589         {
5590                 int scaledwidth, scaledheight;
5591
5592                 r_fb.water.enabled = true;
5593
5594                 // water resolution is usually reduced
5595                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5596                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5597                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5598
5599                 // set up variables that will be used in shader setup
5600                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5601                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5602                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5603                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5604         }
5605
5606         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5607         r_fb.water.numwaterplanes = 0;
5608 }
5609
5610 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5611 {
5612         int planeindex, bestplaneindex, vertexindex;
5613         vec3_t mins, maxs, normal, center, v, n;
5614         vec_t planescore, bestplanescore;
5615         mplane_t plane;
5616         r_waterstate_waterplane_t *p;
5617         texture_t *t = R_GetCurrentTexture(surface->texture);
5618
5619         rsurface.texture = t;
5620         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5621         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5622         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5623                 return;
5624         // average the vertex normals, find the surface bounds (after deformvertexes)
5625         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5626         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5627         VectorCopy(n, normal);
5628         VectorCopy(v, mins);
5629         VectorCopy(v, maxs);
5630         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5631         {
5632                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5633                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5634                 VectorAdd(normal, n, normal);
5635                 mins[0] = min(mins[0], v[0]);
5636                 mins[1] = min(mins[1], v[1]);
5637                 mins[2] = min(mins[2], v[2]);
5638                 maxs[0] = max(maxs[0], v[0]);
5639                 maxs[1] = max(maxs[1], v[1]);
5640                 maxs[2] = max(maxs[2], v[2]);
5641         }
5642         VectorNormalize(normal);
5643         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5644
5645         VectorCopy(normal, plane.normal);
5646         VectorNormalize(plane.normal);
5647         plane.dist = DotProduct(center, plane.normal);
5648         PlaneClassify(&plane);
5649         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5650         {
5651                 // skip backfaces (except if nocullface is set)
5652 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5653 //                      return;
5654                 VectorNegate(plane.normal, plane.normal);
5655                 plane.dist *= -1;
5656                 PlaneClassify(&plane);
5657         }
5658
5659
5660         // find a matching plane if there is one
5661         bestplaneindex = -1;
5662         bestplanescore = 1048576.0f;
5663         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5664         {
5665                 if(p->camera_entity == t->camera_entity)
5666                 {
5667                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5668                         if (bestplaneindex < 0 || bestplanescore > planescore)
5669                         {
5670                                 bestplaneindex = planeindex;
5671                                 bestplanescore = planescore;
5672                         }
5673                 }
5674         }
5675         planeindex = bestplaneindex;
5676         p = r_fb.water.waterplanes + planeindex;
5677
5678         // if this surface does not fit any known plane rendered this frame, add one
5679         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5680         {
5681                 // store the new plane
5682                 planeindex = r_fb.water.numwaterplanes++;
5683                 p = r_fb.water.waterplanes + planeindex;
5684                 p->plane = plane;
5685                 // clear materialflags and pvs
5686                 p->materialflags = 0;
5687                 p->pvsvalid = false;
5688                 p->camera_entity = t->camera_entity;
5689                 VectorCopy(mins, p->mins);
5690                 VectorCopy(maxs, p->maxs);
5691         }
5692         else
5693         {
5694                 // merge mins/maxs when we're adding this surface to the plane
5695                 p->mins[0] = min(p->mins[0], mins[0]);
5696                 p->mins[1] = min(p->mins[1], mins[1]);
5697                 p->mins[2] = min(p->mins[2], mins[2]);
5698                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5699                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5700                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5701         }
5702         // merge this surface's materialflags into the waterplane
5703         p->materialflags |= t->currentmaterialflags;
5704         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5705         {
5706                 // merge this surface's PVS into the waterplane
5707                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5708                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5709                 {
5710                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5711                         p->pvsvalid = true;
5712                 }
5713         }
5714 }
5715
5716 extern cvar_t r_drawparticles;
5717 extern cvar_t r_drawdecals;
5718
5719 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5720 {
5721         int myscissor[4];
5722         r_refdef_view_t originalview;
5723         r_refdef_view_t myview;
5724         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;
5725         r_waterstate_waterplane_t *p;
5726         vec3_t visorigin;
5727         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5728         char vabuf[1024];
5729
5730         originalview = r_refdef.view;
5731
5732         // lowquality hack, temporarily shut down some cvars and restore afterwards
5733         qualityreduction = r_water_lowquality.integer;
5734         if (qualityreduction > 0)
5735         {
5736                 if (qualityreduction >= 1)
5737                 {
5738                         old_r_shadows = r_shadows.integer;
5739                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5740                         old_r_dlight = r_shadow_realtime_dlight.integer;
5741                         Cvar_SetValueQuick(&r_shadows, 0);
5742                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5743                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5744                 }
5745                 if (qualityreduction >= 2)
5746                 {
5747                         old_r_dynamic = r_dynamic.integer;
5748                         old_r_particles = r_drawparticles.integer;
5749                         old_r_decals = r_drawdecals.integer;
5750                         Cvar_SetValueQuick(&r_dynamic, 0);
5751                         Cvar_SetValueQuick(&r_drawparticles, 0);
5752                         Cvar_SetValueQuick(&r_drawdecals, 0);
5753                 }
5754         }
5755
5756         // make sure enough textures are allocated
5757         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5758         {
5759                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5760                 {
5761                         if (!p->texture_refraction)
5762                                 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);
5763                         if (!p->texture_refraction)
5764                                 goto error;
5765                         if (usewaterfbo)
5766                         {
5767                                 if (r_fb.water.depthtexture == NULL)
5768                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5769                                 if (p->fbo_refraction == 0)
5770                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5771                         }
5772                 }
5773                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5774                 {
5775                         if (!p->texture_camera)
5776                                 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);
5777                         if (!p->texture_camera)
5778                                 goto error;
5779                         if (usewaterfbo)
5780                         {
5781                                 if (r_fb.water.depthtexture == NULL)
5782                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5783                                 if (p->fbo_camera == 0)
5784                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5785                         }
5786                 }
5787
5788                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5789                 {
5790                         if (!p->texture_reflection)
5791                                 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);
5792                         if (!p->texture_reflection)
5793                                 goto error;
5794                         if (usewaterfbo)
5795                         {
5796                                 if (r_fb.water.depthtexture == NULL)
5797                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5798                                 if (p->fbo_reflection == 0)
5799                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5800                         }
5801                 }
5802         }
5803
5804         // render views
5805         r_refdef.view = originalview;
5806         r_refdef.view.showdebug = false;
5807         r_refdef.view.width = r_fb.water.waterwidth;
5808         r_refdef.view.height = r_fb.water.waterheight;
5809         r_refdef.view.useclipplane = true;
5810         myview = r_refdef.view;
5811         r_fb.water.renderingscene = true;
5812         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5813         {
5814                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5815                 {
5816                         r_refdef.view = myview;
5817                         if(r_water_scissormode.integer)
5818                         {
5819                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5820                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5821                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5822                         }
5823
5824                         // render reflected scene and copy into texture
5825                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5826                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5827                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5828                         r_refdef.view.clipplane = p->plane;
5829                         // reverse the cullface settings for this render
5830                         r_refdef.view.cullface_front = GL_FRONT;
5831                         r_refdef.view.cullface_back = GL_BACK;
5832                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5833                         {
5834                                 r_refdef.view.usecustompvs = true;
5835                                 if (p->pvsvalid)
5836                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5837                                 else
5838                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5839                         }
5840
5841                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5842                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5843                         R_ClearScreen(r_refdef.fogenabled);
5844                         if(r_water_scissormode.integer & 2)
5845                                 R_View_UpdateWithScissor(myscissor);
5846                         else
5847                                 R_View_Update();
5848                         R_AnimCache_CacheVisibleEntities();
5849                         if(r_water_scissormode.integer & 1)
5850                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5851                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5852
5853                         if (!p->fbo_reflection)
5854                                 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);
5855                         r_fb.water.hideplayer = false;
5856                 }
5857
5858                 // render the normal view scene and copy into texture
5859                 // (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)
5860                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5861                 {
5862                         r_refdef.view = myview;
5863                         if(r_water_scissormode.integer)
5864                         {
5865                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5866                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5867                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5868                         }
5869
5870                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5871
5872                         r_refdef.view.clipplane = p->plane;
5873                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5874                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5875
5876                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5877                         {
5878                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5879                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5880                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5881                                 R_RenderView_UpdateViewVectors();
5882                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5883                                 {
5884                                         r_refdef.view.usecustompvs = true;
5885                                         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);
5886                                 }
5887                         }
5888
5889                         PlaneClassify(&r_refdef.view.clipplane);
5890
5891                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5892                         R_ClearScreen(r_refdef.fogenabled);
5893                         if(r_water_scissormode.integer & 2)
5894                                 R_View_UpdateWithScissor(myscissor);
5895                         else
5896                                 R_View_Update();
5897                         R_AnimCache_CacheVisibleEntities();
5898                         if(r_water_scissormode.integer & 1)
5899                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5900                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5901
5902                         if (!p->fbo_refraction)
5903                                 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);
5904                         r_fb.water.hideplayer = false;
5905                 }
5906                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5907                 {
5908                         r_refdef.view = myview;
5909
5910                         r_refdef.view.clipplane = p->plane;
5911                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5912                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5913
5914                         r_refdef.view.width = r_fb.water.camerawidth;
5915                         r_refdef.view.height = r_fb.water.cameraheight;
5916                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5917                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5918                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5919                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5920
5921                         if(p->camera_entity)
5922                         {
5923                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5924                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5925                         }
5926
5927                         // note: all of the view is used for displaying... so
5928                         // there is no use in scissoring
5929
5930                         // reverse the cullface settings for this render
5931                         r_refdef.view.cullface_front = GL_FRONT;
5932                         r_refdef.view.cullface_back = GL_BACK;
5933                         // also reverse the view matrix
5934                         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
5935                         R_RenderView_UpdateViewVectors();
5936                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5937                         {
5938                                 r_refdef.view.usecustompvs = true;
5939                                 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);
5940                         }
5941                         
5942                         // camera needs no clipplane
5943                         r_refdef.view.useclipplane = false;
5944
5945                         PlaneClassify(&r_refdef.view.clipplane);
5946
5947                         r_fb.water.hideplayer = false;
5948
5949                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5950                         R_ClearScreen(r_refdef.fogenabled);
5951                         R_View_Update();
5952                         R_AnimCache_CacheVisibleEntities();
5953                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5954
5955                         if (!p->fbo_camera)
5956                                 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);
5957                         r_fb.water.hideplayer = false;
5958                 }
5959
5960         }
5961         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5962         r_fb.water.renderingscene = false;
5963         r_refdef.view = originalview;
5964         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5965         if (!r_fb.water.depthtexture)
5966                 R_ClearScreen(r_refdef.fogenabled);
5967         R_View_Update();
5968         R_AnimCache_CacheVisibleEntities();
5969         goto finish;
5970 error:
5971         r_refdef.view = originalview;
5972         r_fb.water.renderingscene = false;
5973         Cvar_SetValueQuick(&r_water, 0);
5974         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5975 finish:
5976         // lowquality hack, restore cvars
5977         if (qualityreduction > 0)
5978         {
5979                 if (qualityreduction >= 1)
5980                 {
5981                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5982                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5983                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5984                 }
5985                 if (qualityreduction >= 2)
5986                 {
5987                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5988                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5989                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5990                 }
5991         }
5992 }
5993
5994 static void R_Bloom_StartFrame(void)
5995 {
5996         int i;
5997         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5998         int viewwidth, viewheight;
5999         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
6000         textype_t textype = TEXTYPE_COLORBUFFER;
6001
6002         switch (vid.renderpath)
6003         {
6004         case RENDERPATH_GL20:
6005                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
6006                 if (vid.support.ext_framebuffer_object)
6007                 {
6008                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
6009                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
6010                 }
6011                 break;
6012         case RENDERPATH_GL11:
6013         case RENDERPATH_GL13:
6014         case RENDERPATH_GLES1:
6015         case RENDERPATH_GLES2:
6016         case RENDERPATH_D3D9:
6017         case RENDERPATH_D3D10:
6018         case RENDERPATH_D3D11:
6019                 r_fb.usedepthtextures = false;
6020                 break;
6021         case RENDERPATH_SOFT:
6022                 r_fb.usedepthtextures = true;
6023                 break;
6024         }
6025
6026         if (r_viewscale_fpsscaling.integer)
6027         {
6028                 double actualframetime;
6029                 double targetframetime;
6030                 double adjust;
6031                 actualframetime = r_refdef.lastdrawscreentime;
6032                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6033                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6034                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6035                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6036                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6037                 viewscalefpsadjusted += adjust;
6038                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6039         }
6040         else
6041                 viewscalefpsadjusted = 1.0f;
6042
6043         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6044
6045         switch(vid.renderpath)
6046         {
6047         case RENDERPATH_GL20:
6048         case RENDERPATH_D3D9:
6049         case RENDERPATH_D3D10:
6050         case RENDERPATH_D3D11:
6051         case RENDERPATH_SOFT:
6052         case RENDERPATH_GLES2:
6053                 break;
6054         case RENDERPATH_GL11:
6055         case RENDERPATH_GL13:
6056         case RENDERPATH_GLES1:
6057                 return;
6058         }
6059
6060         // set bloomwidth and bloomheight to the bloom resolution that will be
6061         // used (often less than the screen resolution for faster rendering)
6062         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.width);
6063         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6064         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6065         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6066         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6067
6068         // calculate desired texture sizes
6069         if (vid.support.arb_texture_non_power_of_two)
6070         {
6071                 screentexturewidth = vid.width;
6072                 screentextureheight = vid.height;
6073                 bloomtexturewidth = r_fb.bloomwidth;
6074                 bloomtextureheight = r_fb.bloomheight;
6075         }
6076         else
6077         {
6078                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6079                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6080                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6081                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6082         }
6083
6084         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))
6085         {
6086                 Cvar_SetValueQuick(&r_bloom, 0);
6087                 Cvar_SetValueQuick(&r_motionblur, 0);
6088                 Cvar_SetValueQuick(&r_damageblur, 0);
6089         }
6090
6091         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6092          && !r_bloom.integer
6093          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6094          && !useviewfbo
6095          && r_viewscale.value == 1.0f
6096          && !r_viewscale_fpsscaling.integer)
6097                 screentexturewidth = screentextureheight = 0;
6098         if (!r_bloom.integer)
6099                 bloomtexturewidth = bloomtextureheight = 0;
6100
6101         // allocate textures as needed
6102         if (r_fb.screentexturewidth != screentexturewidth
6103          || r_fb.screentextureheight != screentextureheight
6104          || r_fb.bloomtexturewidth != bloomtexturewidth
6105          || r_fb.bloomtextureheight != bloomtextureheight
6106          || r_fb.textype != textype
6107          || useviewfbo != (r_fb.fbo != 0))
6108         {
6109                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6110                 {
6111                         if (r_fb.bloomtexture[i])
6112                                 R_FreeTexture(r_fb.bloomtexture[i]);
6113                         r_fb.bloomtexture[i] = NULL;
6114
6115                         if (r_fb.bloomfbo[i])
6116                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6117                         r_fb.bloomfbo[i] = 0;
6118                 }
6119
6120                 if (r_fb.fbo)
6121                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6122                 r_fb.fbo = 0;
6123
6124                 if (r_fb.colortexture)
6125                         R_FreeTexture(r_fb.colortexture);
6126                 r_fb.colortexture = NULL;
6127
6128                 if (r_fb.depthtexture)
6129                         R_FreeTexture(r_fb.depthtexture);
6130                 r_fb.depthtexture = NULL;
6131
6132                 if (r_fb.ghosttexture)
6133                         R_FreeTexture(r_fb.ghosttexture);
6134                 r_fb.ghosttexture = NULL;
6135
6136                 r_fb.screentexturewidth = screentexturewidth;
6137                 r_fb.screentextureheight = screentextureheight;
6138                 r_fb.bloomtexturewidth = bloomtexturewidth;
6139                 r_fb.bloomtextureheight = bloomtextureheight;
6140                 r_fb.textype = textype;
6141
6142                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6143                 {
6144                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6145                                 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);
6146                         r_fb.ghosttexture_valid = false;
6147                         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);
6148                         if (useviewfbo)
6149                         {
6150                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6151                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6152                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6153                         }
6154                 }
6155
6156                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6157                 {
6158                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6159                         {
6160                                 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);
6161                                 if (useviewfbo)
6162                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6163                         }
6164                 }
6165         }
6166
6167         // bloom texture is a different resolution
6168         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.width);
6169         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6170         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6171         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6172         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6173
6174         // set up a texcoord array for the full resolution screen image
6175         // (we have to keep this around to copy back during final render)
6176         r_fb.screentexcoord2f[0] = 0;
6177         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6178         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6179         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6180         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6181         r_fb.screentexcoord2f[5] = 0;
6182         r_fb.screentexcoord2f[6] = 0;
6183         r_fb.screentexcoord2f[7] = 0;
6184
6185         if(r_fb.fbo) 
6186         {
6187                 for (i = 1;i < 8;i += 2)
6188                 {
6189                         r_fb.screentexcoord2f[i] += 1 - (float)(viewheight + r_refdef.view.y) / (float)r_fb.screentextureheight;
6190                 }
6191         }
6192
6193         // set up a texcoord array for the reduced resolution bloom image
6194         // (which will be additive blended over the screen image)
6195         r_fb.bloomtexcoord2f[0] = 0;
6196         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6197         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6198         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6199         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6200         r_fb.bloomtexcoord2f[5] = 0;
6201         r_fb.bloomtexcoord2f[6] = 0;
6202         r_fb.bloomtexcoord2f[7] = 0;
6203
6204         switch(vid.renderpath)
6205         {
6206         case RENDERPATH_GL11:
6207         case RENDERPATH_GL13:
6208         case RENDERPATH_GL20:
6209         case RENDERPATH_SOFT:
6210         case RENDERPATH_GLES1:
6211         case RENDERPATH_GLES2:
6212                 break;
6213         case RENDERPATH_D3D9:
6214         case RENDERPATH_D3D10:
6215         case RENDERPATH_D3D11:
6216                 for (i = 0;i < 4;i++)
6217                 {
6218                         r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6219                         r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6220                         r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6221                         r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6222                 }
6223                 break;
6224         }
6225
6226         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, 0, 0, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6227
6228         if (r_fb.fbo)
6229                 r_refdef.view.clear = true;
6230 }
6231
6232 static void R_Bloom_MakeTexture(void)
6233 {
6234         int x, range, dir;
6235         float xoffset, yoffset, r, brighten;
6236         rtexture_t *intex;
6237         float colorscale = r_bloom_colorscale.value;
6238
6239         r_refdef.stats.bloom++;
6240     
6241 #if 0
6242     // this copy is unnecessary since it happens in R_BlendView already
6243         if (!r_fb.fbo)
6244         {
6245                 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);
6246                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6247         }
6248 #endif
6249
6250         // scale down screen texture to the bloom texture size
6251         CHECKGLERROR
6252         r_fb.bloomindex = 0;
6253         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6254         R_SetViewport(&r_fb.bloomviewport);
6255         GL_DepthTest(false);
6256         GL_BlendFunc(GL_ONE, GL_ZERO);
6257         GL_Color(colorscale, colorscale, colorscale, 1);
6258         // 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...
6259         switch(vid.renderpath)
6260         {
6261         case RENDERPATH_GL11:
6262         case RENDERPATH_GL13:
6263         case RENDERPATH_GL20:
6264         case RENDERPATH_GLES1:
6265         case RENDERPATH_GLES2:
6266         case RENDERPATH_SOFT:
6267                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6268                 break;
6269         case RENDERPATH_D3D9:
6270         case RENDERPATH_D3D10:
6271         case RENDERPATH_D3D11:
6272                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6273                 break;
6274         }
6275         // TODO: do boxfilter scale-down in shader?
6276         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6277         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6278         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6279
6280         // we now have a properly scaled bloom image
6281         if (!r_fb.bloomfbo[r_fb.bloomindex])
6282         {
6283                 // copy it into the bloom texture
6284                 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);
6285                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6286         }
6287
6288         // multiply bloom image by itself as many times as desired
6289         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6290         {
6291                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6292                 r_fb.bloomindex ^= 1;
6293                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6294                 x *= 2;
6295                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6296                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6297                 {
6298                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6299                         GL_Color(r,r,r,1); // apply fix factor
6300                 }
6301                 else
6302                 {
6303                         if(x <= 2)
6304                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6305                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6306                         GL_Color(1,1,1,1); // no fix factor supported here
6307                 }
6308                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6309                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6310                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6311                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6312
6313                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6314                 {
6315                         // copy the darkened image to a texture
6316                         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);
6317                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6318                 }
6319         }
6320
6321         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6322         brighten = r_bloom_brighten.value;
6323         brighten = sqrt(brighten);
6324         if(range >= 1)
6325                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6326
6327         for (dir = 0;dir < 2;dir++)
6328         {
6329                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6330                 r_fb.bloomindex ^= 1;
6331                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6332                 // blend on at multiple vertical offsets to achieve a vertical blur
6333                 // TODO: do offset blends using GLSL
6334                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6335                 GL_BlendFunc(GL_ONE, GL_ZERO);
6336                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6337                 for (x = -range;x <= range;x++)
6338                 {
6339                         if (!dir){xoffset = 0;yoffset = x;}
6340                         else {xoffset = x;yoffset = 0;}
6341                         xoffset /= (float)r_fb.bloomtexturewidth;
6342                         yoffset /= (float)r_fb.bloomtextureheight;
6343                         // compute a texcoord array with the specified x and y offset
6344                         r_fb.offsettexcoord2f[0] = xoffset+r_fb.bloomtexcoord2f[0];
6345                         r_fb.offsettexcoord2f[1] = yoffset+r_fb.bloomtexcoord2f[1];
6346                         r_fb.offsettexcoord2f[2] = xoffset+r_fb.bloomtexcoord2f[2];
6347                         r_fb.offsettexcoord2f[3] = yoffset+r_fb.bloomtexcoord2f[3];
6348                         r_fb.offsettexcoord2f[4] = xoffset+r_fb.bloomtexcoord2f[4];
6349                         r_fb.offsettexcoord2f[5] = yoffset+r_fb.bloomtexcoord2f[5];
6350                         r_fb.offsettexcoord2f[6] = xoffset+r_fb.bloomtexcoord2f[6];
6351                         r_fb.offsettexcoord2f[7] = yoffset+r_fb.bloomtexcoord2f[7];
6352                         // this r value looks like a 'dot' particle, fading sharply to
6353                         // black at the edges
6354                         // (probably not realistic but looks good enough)
6355                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6356                         //r = brighten/(range*2+1);
6357                         r = brighten / (range * 2 + 1);
6358                         if(range >= 1)
6359                                 r *= (1 - x*x/(float)(range*range));
6360                         GL_Color(r, r, r, 1);
6361                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6362                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6363                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6364                         GL_BlendFunc(GL_ONE, GL_ONE);
6365                 }
6366
6367                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6368                 {
6369                         // copy the vertically or horizontally blurred bloom view to a texture
6370                         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);
6371                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6372                 }
6373         }
6374 }
6375
6376 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6377 {
6378         unsigned int permutation;
6379         float uservecs[4][4];
6380
6381         switch (vid.renderpath)
6382         {
6383         case RENDERPATH_GL20:
6384         case RENDERPATH_D3D9:
6385         case RENDERPATH_D3D10:
6386         case RENDERPATH_D3D11:
6387         case RENDERPATH_SOFT:
6388         case RENDERPATH_GLES2:
6389                 permutation =
6390                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6391                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6392                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6393                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6394                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6395
6396                 if (r_fb.colortexture)
6397                 {
6398                         if (!r_fb.fbo)
6399                         {
6400                                 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);
6401                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6402                         }
6403
6404                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6405                         {
6406                                 // declare variables
6407                                 float blur_factor, blur_mouseaccel, blur_velocity;
6408                                 static float blur_average; 
6409                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6410
6411                                 // set a goal for the factoring
6412                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6413                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6414                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6415                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6416                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6417                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6418
6419                                 // from the goal, pick an averaged value between goal and last value
6420                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6421                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6422
6423                                 // enforce minimum amount of blur 
6424                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6425
6426                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6427
6428                                 // calculate values into a standard alpha
6429                                 cl.motionbluralpha = 1 - exp(-
6430                                                 (
6431                                                  (r_motionblur.value * blur_factor / 80)
6432                                                  +
6433                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6434                                                 )
6435                                                 /
6436                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6437                                           );
6438
6439                                 // randomization for the blur value to combat persistent ghosting
6440                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6441                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6442
6443                                 // apply the blur
6444                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6445                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6446                                 {
6447                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6448                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6449                                         switch(vid.renderpath)
6450                                         {
6451                                         case RENDERPATH_GL11:
6452                                         case RENDERPATH_GL13:
6453                                         case RENDERPATH_GL20:
6454                                         case RENDERPATH_GLES1:
6455                                         case RENDERPATH_GLES2:
6456                                         case RENDERPATH_SOFT:
6457                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6458                                                 break;
6459                                         case RENDERPATH_D3D9:
6460                                         case RENDERPATH_D3D10:
6461                                         case RENDERPATH_D3D11:
6462                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6463                                                 break;
6464                                         }
6465                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6466                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6467                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6468                                 }
6469
6470                                 // updates old view angles for next pass
6471                                 VectorCopy(cl.viewangles, blur_oldangles);
6472
6473                                 // copy view into the ghost texture
6474                                 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);
6475                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6476                                 r_fb.ghosttexture_valid = true;
6477                         }
6478                 }
6479                 else
6480                 {
6481                         // no r_fb.colortexture means we're rendering to the real fb
6482                         // we may still have to do view tint...
6483                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6484                         {
6485                                 // apply a color tint to the whole view
6486                                 R_ResetViewRendering2D(0, NULL, NULL);
6487                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6488                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6489                                 R_SetupShader_Generic_NoTexture(false, true);
6490                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6491                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6492                         }
6493                         break; // no screen processing, no bloom, skip it
6494                 }
6495
6496                 if (r_fb.bloomtexture[0])
6497                 {
6498                         // make the bloom texture
6499                         R_Bloom_MakeTexture();
6500                 }
6501
6502 #if _MSC_VER >= 1400
6503 #define sscanf sscanf_s
6504 #endif
6505                 memset(uservecs, 0, sizeof(uservecs));
6506                 if (r_glsl_postprocess_uservec1_enable.integer)
6507                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6508                 if (r_glsl_postprocess_uservec2_enable.integer)
6509                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6510                 if (r_glsl_postprocess_uservec3_enable.integer)
6511                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6512                 if (r_glsl_postprocess_uservec4_enable.integer)
6513                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6514
6515                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6516                 GL_Color(1, 1, 1, 1);
6517                 GL_BlendFunc(GL_ONE, GL_ZERO);
6518
6519                 switch(vid.renderpath)
6520                 {
6521                 case RENDERPATH_GL20:
6522                 case RENDERPATH_GLES2:
6523                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6524                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6525                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6526                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6527                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6528                         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]);
6529                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6530                         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]);
6531                         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]);
6532                         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]);
6533                         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]);
6534                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6535                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6536                         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);
6537                         break;
6538                 case RENDERPATH_D3D9:
6539 #ifdef SUPPORTD3D
6540                         // 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...
6541                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6542                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6543                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6544                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6545                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6546                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6547                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6548                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6549                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6550                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6551                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6552                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6553                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6554                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6555 #endif
6556                         break;
6557                 case RENDERPATH_D3D10:
6558                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6559                         break;
6560                 case RENDERPATH_D3D11:
6561                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6562                         break;
6563                 case RENDERPATH_SOFT:
6564                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6565                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6566                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6567                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6568                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6569                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6570                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6571                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6572                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6573                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6574                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6575                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6576                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6577                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6578                         break;
6579                 default:
6580                         break;
6581                 }
6582                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6583                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6584                 break;
6585         case RENDERPATH_GL11:
6586         case RENDERPATH_GL13:
6587         case RENDERPATH_GLES1:
6588                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6589                 {
6590                         // apply a color tint to the whole view
6591                         R_ResetViewRendering2D(0, NULL, NULL);
6592                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6593                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6594                         R_SetupShader_Generic_NoTexture(false, true);
6595                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6596                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6597                 }
6598                 break;
6599         }
6600 }
6601
6602 matrix4x4_t r_waterscrollmatrix;
6603
6604 void R_UpdateFog(void)
6605 {
6606         // Nehahra fog
6607         if (gamemode == GAME_NEHAHRA)
6608         {
6609                 if (gl_fogenable.integer)
6610                 {
6611                         r_refdef.oldgl_fogenable = true;
6612                         r_refdef.fog_density = gl_fogdensity.value;
6613                         r_refdef.fog_red = gl_fogred.value;
6614                         r_refdef.fog_green = gl_foggreen.value;
6615                         r_refdef.fog_blue = gl_fogblue.value;
6616                         r_refdef.fog_alpha = 1;
6617                         r_refdef.fog_start = 0;
6618                         r_refdef.fog_end = gl_skyclip.value;
6619                         r_refdef.fog_height = 1<<30;
6620                         r_refdef.fog_fadedepth = 128;
6621                 }
6622                 else if (r_refdef.oldgl_fogenable)
6623                 {
6624                         r_refdef.oldgl_fogenable = false;
6625                         r_refdef.fog_density = 0;
6626                         r_refdef.fog_red = 0;
6627                         r_refdef.fog_green = 0;
6628                         r_refdef.fog_blue = 0;
6629                         r_refdef.fog_alpha = 0;
6630                         r_refdef.fog_start = 0;
6631                         r_refdef.fog_end = 0;
6632                         r_refdef.fog_height = 1<<30;
6633                         r_refdef.fog_fadedepth = 128;
6634                 }
6635         }
6636
6637         // fog parms
6638         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6639         r_refdef.fog_start = max(0, r_refdef.fog_start);
6640         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6641
6642         if (r_refdef.fog_density && r_drawfog.integer)
6643         {
6644                 r_refdef.fogenabled = true;
6645                 // this is the point where the fog reaches 0.9986 alpha, which we
6646                 // consider a good enough cutoff point for the texture
6647                 // (0.9986 * 256 == 255.6)
6648                 if (r_fog_exp2.integer)
6649                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6650                 else
6651                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6652                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6653                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6654                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6655                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6656                         R_BuildFogHeightTexture();
6657                 // fog color was already set
6658                 // update the fog texture
6659                 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)
6660                         R_BuildFogTexture();
6661                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6662                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6663         }
6664         else
6665                 r_refdef.fogenabled = false;
6666
6667         // fog color
6668         if (r_refdef.fog_density)
6669         {
6670                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6671                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6672                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6673
6674                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6675                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6676                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6677                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6678
6679                 {
6680                         vec3_t fogvec;
6681                         VectorCopy(r_refdef.fogcolor, fogvec);
6682                         //   color.rgb *= ContrastBoost * SceneBrightness;
6683                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6684                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6685                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6686                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6687                 }
6688         }
6689 }
6690
6691 void R_UpdateVariables(void)
6692 {
6693         R_Textures_Frame();
6694
6695         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6696
6697         r_refdef.farclip = r_farclip_base.value;
6698         if (r_refdef.scene.worldmodel)
6699                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6700         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6701
6702         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6703                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6704         r_refdef.polygonfactor = 0;
6705         r_refdef.polygonoffset = 0;
6706         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6707         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6708
6709         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6710         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6711         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6712         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6713         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6714         if (FAKELIGHT_ENABLED)
6715         {
6716                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6717         }
6718         else if (r_refdef.scene.worldmodel)
6719         {
6720                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6721         }
6722         if (r_showsurfaces.integer)
6723         {
6724                 r_refdef.scene.rtworld = false;
6725                 r_refdef.scene.rtworldshadows = false;
6726                 r_refdef.scene.rtdlight = false;
6727                 r_refdef.scene.rtdlightshadows = false;
6728                 r_refdef.lightmapintensity = 0;
6729         }
6730
6731         switch(vid.renderpath)
6732         {
6733         case RENDERPATH_GL20:
6734         case RENDERPATH_D3D9:
6735         case RENDERPATH_D3D10:
6736         case RENDERPATH_D3D11:
6737         case RENDERPATH_SOFT:
6738         case RENDERPATH_GLES2:
6739                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6740                 {
6741                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6742                         {
6743                                 // build GLSL gamma texture
6744 #define RAMPWIDTH 256
6745                                 unsigned short ramp[RAMPWIDTH * 3];
6746                                 unsigned char rampbgr[RAMPWIDTH][4];
6747                                 int i;
6748
6749                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6750
6751                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6752                                 for(i = 0; i < RAMPWIDTH; ++i)
6753                                 {
6754                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6755                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6756                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6757                                         rampbgr[i][3] = 0;
6758                                 }
6759                                 if (r_texture_gammaramps)
6760                                 {
6761                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6762                                 }
6763                                 else
6764                                 {
6765                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6766                                 }
6767                         }
6768                 }
6769                 else
6770                 {
6771                         // remove GLSL gamma texture
6772                 }
6773                 break;
6774         case RENDERPATH_GL11:
6775         case RENDERPATH_GL13:
6776         case RENDERPATH_GLES1:
6777                 break;
6778         }
6779 }
6780
6781 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6782 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6783 /*
6784 ================
6785 R_SelectScene
6786 ================
6787 */
6788 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6789         if( scenetype != r_currentscenetype ) {
6790                 // store the old scenetype
6791                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6792                 r_currentscenetype = scenetype;
6793                 // move in the new scene
6794                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6795         }
6796 }
6797
6798 /*
6799 ================
6800 R_GetScenePointer
6801 ================
6802 */
6803 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6804 {
6805         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6806         if( scenetype == r_currentscenetype ) {
6807                 return &r_refdef.scene;
6808         } else {
6809                 return &r_scenes_store[ scenetype ];
6810         }
6811 }
6812
6813 static int R_SortEntities_Compare(const void *ap, const void *bp)
6814 {
6815         const entity_render_t *a = *(const entity_render_t **)ap;
6816         const entity_render_t *b = *(const entity_render_t **)bp;
6817
6818         // 1. compare model
6819         if(a->model < b->model)
6820                 return -1;
6821         if(a->model > b->model)
6822                 return +1;
6823
6824         // 2. compare skin
6825         // TODO possibly calculate the REAL skinnum here first using
6826         // skinscenes?
6827         if(a->skinnum < b->skinnum)
6828                 return -1;
6829         if(a->skinnum > b->skinnum)
6830                 return +1;
6831
6832         // everything we compared is equal
6833         return 0;
6834 }
6835 static void R_SortEntities(void)
6836 {
6837         // below or equal 2 ents, sorting never gains anything
6838         if(r_refdef.scene.numentities <= 2)
6839                 return;
6840         // sort
6841         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6842 }
6843
6844 /*
6845 ================
6846 R_RenderView
6847 ================
6848 */
6849 int dpsoftrast_test;
6850 extern cvar_t r_shadow_bouncegrid;
6851 void R_RenderView(void)
6852 {
6853         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6854         int fbo;
6855         rtexture_t *depthtexture;
6856         rtexture_t *colortexture;
6857
6858         dpsoftrast_test = r_test.integer;
6859
6860         if (r_timereport_active)
6861                 R_TimeReport("start");
6862         r_textureframe++; // used only by R_GetCurrentTexture
6863         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6864
6865         if(R_CompileShader_CheckStaticParms())
6866                 R_GLSL_Restart_f();
6867
6868         if (!r_drawentities.integer)
6869                 r_refdef.scene.numentities = 0;
6870         else if (r_sortentities.integer)
6871                 R_SortEntities();
6872
6873         R_AnimCache_ClearCache();
6874         R_FrameData_NewFrame();
6875
6876         /* adjust for stereo display */
6877         if(R_Stereo_Active())
6878         {
6879                 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);
6880                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6881         }
6882
6883         if (r_refdef.view.isoverlay)
6884         {
6885                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6886                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6887                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6888                 R_TimeReport("depthclear");
6889
6890                 r_refdef.view.showdebug = false;
6891
6892                 r_fb.water.enabled = false;
6893                 r_fb.water.numwaterplanes = 0;
6894
6895                 R_RenderScene(0, NULL, NULL);
6896
6897                 r_refdef.view.matrix = originalmatrix;
6898
6899                 CHECKGLERROR
6900                 return;
6901         }
6902
6903         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6904         {
6905                 r_refdef.view.matrix = originalmatrix;
6906                 return;
6907         }
6908
6909         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6910
6911         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6912                 // in sRGB fallback, behave similar to true sRGB: convert this
6913                 // value from linear to sRGB
6914                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6915
6916         R_RenderView_UpdateViewVectors();
6917
6918         R_Shadow_UpdateWorldLightSelection();
6919
6920         R_Bloom_StartFrame();
6921         R_Water_StartFrame();
6922
6923         // now we probably have an fbo to render into
6924         fbo = r_fb.fbo;
6925         depthtexture = r_fb.depthtexture;
6926         colortexture = r_fb.colortexture;
6927
6928         CHECKGLERROR
6929         if (r_timereport_active)
6930                 R_TimeReport("viewsetup");
6931
6932         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6933
6934         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6935         {
6936                 R_ClearScreen(r_refdef.fogenabled);
6937                 if (r_timereport_active)
6938                         R_TimeReport("viewclear");
6939         }
6940         r_refdef.view.clear = true;
6941
6942         r_refdef.view.showdebug = true;
6943
6944         R_View_Update();
6945         if (r_timereport_active)
6946                 R_TimeReport("visibility");
6947
6948         R_AnimCache_CacheVisibleEntities();
6949         if (r_timereport_active)
6950                 R_TimeReport("animcache");
6951
6952         R_Shadow_UpdateBounceGridTexture();
6953         if (r_timereport_active && r_shadow_bouncegrid.integer)
6954                 R_TimeReport("bouncegrid");
6955
6956         r_fb.water.numwaterplanes = 0;
6957         if (r_fb.water.enabled)
6958                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6959
6960         R_RenderScene(fbo, depthtexture, colortexture);
6961         r_fb.water.numwaterplanes = 0;
6962
6963         R_BlendView(fbo, depthtexture, colortexture);
6964         if (r_timereport_active)
6965                 R_TimeReport("blendview");
6966
6967         GL_Scissor(0, 0, vid.width, vid.height);
6968         GL_ScissorTest(false);
6969
6970         r_refdef.view.matrix = originalmatrix;
6971
6972         CHECKGLERROR
6973 }
6974
6975 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6976 {
6977         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6978         {
6979                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6980                 if (r_timereport_active)
6981                         R_TimeReport("waterworld");
6982         }
6983
6984         // don't let sound skip if going slow
6985         if (r_refdef.scene.extraupdate)
6986                 S_ExtraUpdate ();
6987
6988         R_DrawModelsAddWaterPlanes();
6989         if (r_timereport_active)
6990                 R_TimeReport("watermodels");
6991
6992         if (r_fb.water.numwaterplanes)
6993         {
6994                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6995                 if (r_timereport_active)
6996                         R_TimeReport("waterscenes");
6997         }
6998 }
6999
7000 extern cvar_t cl_locs_show;
7001 static void R_DrawLocs(void);
7002 static void R_DrawEntityBBoxes(void);
7003 static void R_DrawModelDecals(void);
7004 extern cvar_t cl_decals_newsystem;
7005 extern qboolean r_shadow_usingdeferredprepass;
7006 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
7007 {
7008         qboolean shadowmapping = false;
7009
7010         if (r_timereport_active)
7011                 R_TimeReport("beginscene");
7012
7013         r_refdef.stats.renders++;
7014
7015         R_UpdateFog();
7016
7017         // don't let sound skip if going slow
7018         if (r_refdef.scene.extraupdate)
7019                 S_ExtraUpdate ();
7020
7021         R_MeshQueue_BeginScene();
7022
7023         R_SkyStartFrame();
7024
7025         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);
7026
7027         if (r_timereport_active)
7028                 R_TimeReport("skystartframe");
7029
7030         if (cl.csqc_vidvars.drawworld)
7031         {
7032                 // don't let sound skip if going slow
7033                 if (r_refdef.scene.extraupdate)
7034                         S_ExtraUpdate ();
7035
7036                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7037                 {
7038                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7039                         if (r_timereport_active)
7040                                 R_TimeReport("worldsky");
7041                 }
7042
7043                 if (R_DrawBrushModelsSky() && r_timereport_active)
7044                         R_TimeReport("bmodelsky");
7045
7046                 if (skyrendermasked && skyrenderlater)
7047                 {
7048                         // we have to force off the water clipping plane while rendering sky
7049                         R_SetupView(false, fbo, depthtexture, colortexture);
7050                         R_Sky();
7051                         R_SetupView(true, fbo, depthtexture, colortexture);
7052                         if (r_timereport_active)
7053                                 R_TimeReport("sky");
7054                 }
7055         }
7056
7057         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7058         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7059                 R_Shadow_PrepareModelShadows();
7060         if (r_timereport_active)
7061                 R_TimeReport("preparelights");
7062
7063         if (R_Shadow_ShadowMappingEnabled())
7064                 shadowmapping = true;
7065
7066         if (r_shadow_usingdeferredprepass)
7067                 R_Shadow_DrawPrepass();
7068
7069         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7070         {
7071                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7072                 if (r_timereport_active)
7073                         R_TimeReport("worlddepth");
7074         }
7075         if (r_depthfirst.integer >= 2)
7076         {
7077                 R_DrawModelsDepth();
7078                 if (r_timereport_active)
7079                         R_TimeReport("modeldepth");
7080         }
7081
7082         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7083         {
7084                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7085                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7086                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7087                 // don't let sound skip if going slow
7088                 if (r_refdef.scene.extraupdate)
7089                         S_ExtraUpdate ();
7090         }
7091
7092         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7093         {
7094                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7095                 if (r_timereport_active)
7096                         R_TimeReport("world");
7097         }
7098
7099         // don't let sound skip if going slow
7100         if (r_refdef.scene.extraupdate)
7101                 S_ExtraUpdate ();
7102
7103         R_DrawModels();
7104         if (r_timereport_active)
7105                 R_TimeReport("models");
7106
7107         // don't let sound skip if going slow
7108         if (r_refdef.scene.extraupdate)
7109                 S_ExtraUpdate ();
7110
7111         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7112         {
7113                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7114                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7115                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7116                 // don't let sound skip if going slow
7117                 if (r_refdef.scene.extraupdate)
7118                         S_ExtraUpdate ();
7119         }
7120
7121         if (!r_shadow_usingdeferredprepass)
7122         {
7123                 R_Shadow_DrawLights();
7124                 if (r_timereport_active)
7125                         R_TimeReport("rtlights");
7126         }
7127
7128         // don't let sound skip if going slow
7129         if (r_refdef.scene.extraupdate)
7130                 S_ExtraUpdate ();
7131
7132         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7133         {
7134                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7135                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7136                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7137                 // don't let sound skip if going slow
7138                 if (r_refdef.scene.extraupdate)
7139                         S_ExtraUpdate ();
7140         }
7141
7142         if (cl.csqc_vidvars.drawworld)
7143         {
7144                 if (cl_decals_newsystem.integer)
7145                 {
7146                         R_DrawModelDecals();
7147                         if (r_timereport_active)
7148                                 R_TimeReport("modeldecals");
7149                 }
7150                 else
7151                 {
7152                         R_DrawDecals();
7153                         if (r_timereport_active)
7154                                 R_TimeReport("decals");
7155                 }
7156
7157                 R_DrawParticles();
7158                 if (r_timereport_active)
7159                         R_TimeReport("particles");
7160
7161                 R_DrawExplosions();
7162                 if (r_timereport_active)
7163                         R_TimeReport("explosions");
7164
7165                 R_DrawLightningBeams();
7166                 if (r_timereport_active)
7167                         R_TimeReport("lightning");
7168         }
7169
7170         if (cl.csqc_loaded)
7171                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7172
7173         if (r_refdef.view.showdebug)
7174         {
7175                 if (cl_locs_show.integer)
7176                 {
7177                         R_DrawLocs();
7178                         if (r_timereport_active)
7179                                 R_TimeReport("showlocs");
7180                 }
7181
7182                 if (r_drawportals.integer)
7183                 {
7184                         R_DrawPortals();
7185                         if (r_timereport_active)
7186                                 R_TimeReport("portals");
7187                 }
7188
7189                 if (r_showbboxes.value > 0)
7190                 {
7191                         R_DrawEntityBBoxes();
7192                         if (r_timereport_active)
7193                                 R_TimeReport("bboxes");
7194                 }
7195         }
7196
7197         if (r_transparent.integer)
7198         {
7199                 R_MeshQueue_RenderTransparent();
7200                 if (r_timereport_active)
7201                         R_TimeReport("drawtrans");
7202         }
7203
7204         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))
7205         {
7206                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7207                 if (r_timereport_active)
7208                         R_TimeReport("worlddebug");
7209                 R_DrawModelsDebug();
7210                 if (r_timereport_active)
7211                         R_TimeReport("modeldebug");
7212         }
7213
7214         if (cl.csqc_vidvars.drawworld)
7215         {
7216                 R_Shadow_DrawCoronas();
7217                 if (r_timereport_active)
7218                         R_TimeReport("coronas");
7219         }
7220
7221 #if 0
7222         {
7223                 GL_DepthTest(false);
7224                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7225                 GL_Color(1, 1, 1, 1);
7226                 qglBegin(GL_POLYGON);
7227                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7228                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7229                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7230                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7231                 qglEnd();
7232                 qglBegin(GL_POLYGON);
7233                 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]);
7234                 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]);
7235                 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]);
7236                 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]);
7237                 qglEnd();
7238                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7239         }
7240 #endif
7241
7242         // don't let sound skip if going slow
7243         if (r_refdef.scene.extraupdate)
7244                 S_ExtraUpdate ();
7245 }
7246
7247 static const unsigned short bboxelements[36] =
7248 {
7249         5, 1, 3, 5, 3, 7,
7250         6, 2, 0, 6, 0, 4,
7251         7, 3, 2, 7, 2, 6,
7252         4, 0, 1, 4, 1, 5,
7253         4, 5, 7, 4, 7, 6,
7254         1, 0, 2, 1, 2, 3,
7255 };
7256
7257 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7258 {
7259         int i;
7260         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7261
7262         RSurf_ActiveWorldEntity();
7263
7264         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7265         GL_DepthMask(false);
7266         GL_DepthRange(0, 1);
7267         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7268 //      R_Mesh_ResetTextureState();
7269
7270         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7271         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7272         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7273         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7274         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7275         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7276         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7277         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7278         R_FillColors(color4f, 8, cr, cg, cb, ca);
7279         if (r_refdef.fogenabled)
7280         {
7281                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7282                 {
7283                         f1 = RSurf_FogVertex(v);
7284                         f2 = 1 - f1;
7285                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7286                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7287                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7288                 }
7289         }
7290         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7291         R_Mesh_ResetTextureState();
7292         R_SetupShader_Generic_NoTexture(false, false);
7293         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7294 }
7295
7296 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7297 {
7298         prvm_prog_t *prog = SVVM_prog;
7299         int i;
7300         float color[4];
7301         prvm_edict_t *edict;
7302
7303         // this function draws bounding boxes of server entities
7304         if (!sv.active)
7305                 return;
7306
7307         GL_CullFace(GL_NONE);
7308         R_SetupShader_Generic_NoTexture(false, false);
7309
7310         for (i = 0;i < numsurfaces;i++)
7311         {
7312                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7313                 switch ((int)PRVM_serveredictfloat(edict, solid))
7314                 {
7315                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7316                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7317                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7318                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7319                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7320                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7321                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7322                 }
7323                 color[3] *= r_showbboxes.value;
7324                 color[3] = bound(0, color[3], 1);
7325                 GL_DepthTest(!r_showdisabledepthtest.integer);
7326                 GL_CullFace(r_refdef.view.cullface_front);
7327                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7328         }
7329 }
7330
7331 static void R_DrawEntityBBoxes(void)
7332 {
7333         int i;
7334         prvm_edict_t *edict;
7335         vec3_t center;
7336         prvm_prog_t *prog = SVVM_prog;
7337
7338         // this function draws bounding boxes of server entities
7339         if (!sv.active)
7340                 return;
7341
7342         for (i = 0;i < prog->num_edicts;i++)
7343         {
7344                 edict = PRVM_EDICT_NUM(i);
7345                 if (edict->priv.server->free)
7346                         continue;
7347                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7348                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7349                         continue;
7350                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7351                         continue;
7352                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7353                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7354         }
7355 }
7356
7357 static const int nomodelelement3i[24] =
7358 {
7359         5, 2, 0,
7360         5, 1, 2,
7361         5, 0, 3,
7362         5, 3, 1,
7363         0, 2, 4,
7364         2, 1, 4,
7365         3, 0, 4,
7366         1, 3, 4
7367 };
7368
7369 static const unsigned short nomodelelement3s[24] =
7370 {
7371         5, 2, 0,
7372         5, 1, 2,
7373         5, 0, 3,
7374         5, 3, 1,
7375         0, 2, 4,
7376         2, 1, 4,
7377         3, 0, 4,
7378         1, 3, 4
7379 };
7380
7381 static const float nomodelvertex3f[6*3] =
7382 {
7383         -16,   0,   0,
7384          16,   0,   0,
7385           0, -16,   0,
7386           0,  16,   0,
7387           0,   0, -16,
7388           0,   0,  16
7389 };
7390
7391 static const float nomodelcolor4f[6*4] =
7392 {
7393         0.0f, 0.0f, 0.5f, 1.0f,
7394         0.0f, 0.0f, 0.5f, 1.0f,
7395         0.0f, 0.5f, 0.0f, 1.0f,
7396         0.0f, 0.5f, 0.0f, 1.0f,
7397         0.5f, 0.0f, 0.0f, 1.0f,
7398         0.5f, 0.0f, 0.0f, 1.0f
7399 };
7400
7401 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7402 {
7403         int i;
7404         float f1, f2, *c;
7405         float color4f[6*4];
7406
7407         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);
7408
7409         // this is only called once per entity so numsurfaces is always 1, and
7410         // surfacelist is always {0}, so this code does not handle batches
7411
7412         if (rsurface.ent_flags & RENDER_ADDITIVE)
7413         {
7414                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7415                 GL_DepthMask(false);
7416         }
7417         else if (rsurface.colormod[3] < 1)
7418         {
7419                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7420                 GL_DepthMask(false);
7421         }
7422         else
7423         {
7424                 GL_BlendFunc(GL_ONE, GL_ZERO);
7425                 GL_DepthMask(true);
7426         }
7427         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7428         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7429         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7430         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7431         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7432         for (i = 0, c = color4f;i < 6;i++, c += 4)
7433         {
7434                 c[0] *= rsurface.colormod[0];
7435                 c[1] *= rsurface.colormod[1];
7436                 c[2] *= rsurface.colormod[2];
7437                 c[3] *= rsurface.colormod[3];
7438         }
7439         if (r_refdef.fogenabled)
7440         {
7441                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7442                 {
7443                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7444                         f2 = 1 - f1;
7445                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7446                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7447                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7448                 }
7449         }
7450 //      R_Mesh_ResetTextureState();
7451         R_SetupShader_Generic_NoTexture(false, false);
7452         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7453         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7454 }
7455
7456 void R_DrawNoModel(entity_render_t *ent)
7457 {
7458         vec3_t org;
7459         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7460         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7461                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : MESHQUEUE_SORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7462         else
7463                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7464 }
7465
7466 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7467 {
7468         vec3_t right1, right2, diff, normal;
7469
7470         VectorSubtract (org2, org1, normal);
7471
7472         // calculate 'right' vector for start
7473         VectorSubtract (r_refdef.view.origin, org1, diff);
7474         CrossProduct (normal, diff, right1);
7475         VectorNormalize (right1);
7476
7477         // calculate 'right' vector for end
7478         VectorSubtract (r_refdef.view.origin, org2, diff);
7479         CrossProduct (normal, diff, right2);
7480         VectorNormalize (right2);
7481
7482         vert[ 0] = org1[0] + width * right1[0];
7483         vert[ 1] = org1[1] + width * right1[1];
7484         vert[ 2] = org1[2] + width * right1[2];
7485         vert[ 3] = org1[0] - width * right1[0];
7486         vert[ 4] = org1[1] - width * right1[1];
7487         vert[ 5] = org1[2] - width * right1[2];
7488         vert[ 6] = org2[0] - width * right2[0];
7489         vert[ 7] = org2[1] - width * right2[1];
7490         vert[ 8] = org2[2] - width * right2[2];
7491         vert[ 9] = org2[0] + width * right2[0];
7492         vert[10] = org2[1] + width * right2[1];
7493         vert[11] = org2[2] + width * right2[2];
7494 }
7495
7496 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)
7497 {
7498         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7499         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7500         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7501         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7502         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7503         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7504         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7505         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7506         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7507         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7508         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7509         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7510 }
7511
7512 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7513 {
7514         int i;
7515         float *vertex3f;
7516         float v[3];
7517         VectorSet(v, x, y, z);
7518         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7519                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7520                         break;
7521         if (i == mesh->numvertices)
7522         {
7523                 if (mesh->numvertices < mesh->maxvertices)
7524                 {
7525                         VectorCopy(v, vertex3f);
7526                         mesh->numvertices++;
7527                 }
7528                 return mesh->numvertices;
7529         }
7530         else
7531                 return i;
7532 }
7533
7534 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7535 {
7536         int i;
7537         int *e, element[3];
7538         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7539         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7540         e = mesh->element3i + mesh->numtriangles * 3;
7541         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7542         {
7543                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7544                 if (mesh->numtriangles < mesh->maxtriangles)
7545                 {
7546                         *e++ = element[0];
7547                         *e++ = element[1];
7548                         *e++ = element[2];
7549                         mesh->numtriangles++;
7550                 }
7551                 element[1] = element[2];
7552         }
7553 }
7554
7555 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7556 {
7557         int i;
7558         int *e, element[3];
7559         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7560         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7561         e = mesh->element3i + mesh->numtriangles * 3;
7562         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7563         {
7564                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7565                 if (mesh->numtriangles < mesh->maxtriangles)
7566                 {
7567                         *e++ = element[0];
7568                         *e++ = element[1];
7569                         *e++ = element[2];
7570                         mesh->numtriangles++;
7571                 }
7572                 element[1] = element[2];
7573         }
7574 }
7575
7576 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7577 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7578 {
7579         int planenum, planenum2;
7580         int w;
7581         int tempnumpoints;
7582         mplane_t *plane, *plane2;
7583         double maxdist;
7584         double temppoints[2][256*3];
7585         // figure out how large a bounding box we need to properly compute this brush
7586         maxdist = 0;
7587         for (w = 0;w < numplanes;w++)
7588                 maxdist = max(maxdist, fabs(planes[w].dist));
7589         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7590         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7591         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7592         {
7593                 w = 0;
7594                 tempnumpoints = 4;
7595                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7596                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7597                 {
7598                         if (planenum2 == planenum)
7599                                 continue;
7600                         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);
7601                         w = !w;
7602                 }
7603                 if (tempnumpoints < 3)
7604                         continue;
7605                 // generate elements forming a triangle fan for this polygon
7606                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7607         }
7608 }
7609
7610 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)
7611 {
7612         texturelayer_t *layer;
7613         layer = t->currentlayers + t->currentnumlayers++;
7614         layer->type = type;
7615         layer->depthmask = depthmask;
7616         layer->blendfunc1 = blendfunc1;
7617         layer->blendfunc2 = blendfunc2;
7618         layer->texture = texture;
7619         layer->texmatrix = *matrix;
7620         layer->color[0] = r;
7621         layer->color[1] = g;
7622         layer->color[2] = b;
7623         layer->color[3] = a;
7624 }
7625
7626 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7627 {
7628         if(parms[0] == 0 && parms[1] == 0)
7629                 return false;
7630         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7631                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7632                         return false;
7633         return true;
7634 }
7635
7636 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7637 {
7638         double index, f;
7639         index = parms[2] + rsurface.shadertime * parms[3];
7640         index -= floor(index);
7641         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7642         {
7643         default:
7644         case Q3WAVEFUNC_NONE:
7645         case Q3WAVEFUNC_NOISE:
7646         case Q3WAVEFUNC_COUNT:
7647                 f = 0;
7648                 break;
7649         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7650         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7651         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7652         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7653         case Q3WAVEFUNC_TRIANGLE:
7654                 index *= 4;
7655                 f = index - floor(index);
7656                 if (index < 1)
7657                 {
7658                         // f = f;
7659                 }
7660                 else if (index < 2)
7661                         f = 1 - f;
7662                 else if (index < 3)
7663                         f = -f;
7664                 else
7665                         f = -(1 - f);
7666                 break;
7667         }
7668         f = parms[0] + parms[1] * f;
7669         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7670                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7671         return (float) f;
7672 }
7673
7674 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7675 {
7676         int w, h, idx;
7677         double f;
7678         double offsetd[2];
7679         float tcmat[12];
7680         matrix4x4_t matrix, temp;
7681         switch(tcmod->tcmod)
7682         {
7683                 case Q3TCMOD_COUNT:
7684                 case Q3TCMOD_NONE:
7685                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7686                                 matrix = r_waterscrollmatrix;
7687                         else
7688                                 matrix = identitymatrix;
7689                         break;
7690                 case Q3TCMOD_ENTITYTRANSLATE:
7691                         // this is used in Q3 to allow the gamecode to control texcoord
7692                         // scrolling on the entity, which is not supported in darkplaces yet.
7693                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7694                         break;
7695                 case Q3TCMOD_ROTATE:
7696                         f = tcmod->parms[0] * rsurface.shadertime;
7697                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7698                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7699                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7700                         break;
7701                 case Q3TCMOD_SCALE:
7702                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7703                         break;
7704                 case Q3TCMOD_SCROLL:
7705                         // extra care is needed because of precision breakdown with large values of time
7706                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7707                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7708                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7709                         break;
7710                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7711                         w = (int) tcmod->parms[0];
7712                         h = (int) tcmod->parms[1];
7713                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7714                         f = f - floor(f);
7715                         idx = (int) floor(f * w * h);
7716                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7717                         break;
7718                 case Q3TCMOD_STRETCH:
7719                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7720                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7721                         break;
7722                 case Q3TCMOD_TRANSFORM:
7723                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7724                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7725                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7726                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7727                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7728                         break;
7729                 case Q3TCMOD_TURBULENT:
7730                         // this is handled in the RSurf_PrepareVertices function
7731                         matrix = identitymatrix;
7732                         break;
7733         }
7734         temp = *texmatrix;
7735         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7736 }
7737
7738 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7739 {
7740         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7741         char name[MAX_QPATH];
7742         skinframe_t *skinframe;
7743         unsigned char pixels[296*194];
7744         strlcpy(cache->name, skinname, sizeof(cache->name));
7745         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7746         if (developer_loading.integer)
7747                 Con_Printf("loading %s\n", name);
7748         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7749         if (!skinframe || !skinframe->base)
7750         {
7751                 unsigned char *f;
7752                 fs_offset_t filesize;
7753                 skinframe = NULL;
7754                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7755                 if (f)
7756                 {
7757                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7758                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7759                         Mem_Free(f);
7760                 }
7761         }
7762         cache->skinframe = skinframe;
7763 }
7764
7765 texture_t *R_GetCurrentTexture(texture_t *t)
7766 {
7767         int i;
7768         const entity_render_t *ent = rsurface.entity;
7769         dp_model_t *model = ent->model;
7770         q3shaderinfo_layer_tcmod_t *tcmod;
7771
7772         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent && !rsurface.forcecurrenttextureupdate)
7773                 return t->currentframe;
7774         t->update_lastrenderframe = r_textureframe;
7775         t->update_lastrenderentity = (void *)ent;
7776
7777         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7778                 t->camera_entity = ent->entitynumber;
7779         else
7780                 t->camera_entity = 0;
7781
7782         // switch to an alternate material if this is a q1bsp animated material
7783         {
7784                 texture_t *texture = t;
7785                 int s = rsurface.ent_skinnum;
7786                 if ((unsigned int)s >= (unsigned int)model->numskins)
7787                         s = 0;
7788                 if (model->skinscenes)
7789                 {
7790                         if (model->skinscenes[s].framecount > 1)
7791                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7792                         else
7793                                 s = model->skinscenes[s].firstframe;
7794                 }
7795                 if (s > 0)
7796                         t = t + s * model->num_surfaces;
7797                 if (t->animated)
7798                 {
7799                         // use an alternate animation if the entity's frame is not 0,
7800                         // and only if the texture has an alternate animation
7801                         if (rsurface.ent_alttextures && t->anim_total[1])
7802                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7803                         else
7804                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7805                 }
7806                 texture->currentframe = t;
7807         }
7808
7809         // update currentskinframe to be a qw skin or animation frame
7810         if (rsurface.ent_qwskin >= 0)
7811         {
7812                 i = rsurface.ent_qwskin;
7813                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7814                 {
7815                         r_qwskincache_size = cl.maxclients;
7816                         if (r_qwskincache)
7817                                 Mem_Free(r_qwskincache);
7818                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7819                 }
7820                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7821                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7822                 t->currentskinframe = r_qwskincache[i].skinframe;
7823                 if (t->currentskinframe == NULL)
7824                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7825         }
7826         else if (t->numskinframes >= 2)
7827                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7828         if (t->backgroundnumskinframes >= 2)
7829                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7830
7831         t->currentmaterialflags = t->basematerialflags;
7832         t->currentalpha = rsurface.colormod[3];
7833         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7834                 t->currentalpha *= r_wateralpha.value;
7835         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7836                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7837         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7838                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7839         if (!(rsurface.ent_flags & RENDER_LIGHT))
7840                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7841         else if (FAKELIGHT_ENABLED)
7842         {
7843                 // no modellight if using fakelight for the map
7844         }
7845         else if ((rsurface.modeltexcoordlightmap2f == NULL || (rsurface.ent_flags & (RENDER_DYNAMICMODELLIGHT | RENDER_CUSTOMIZEDMODELLIGHT))) && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7846         {
7847                 // pick a model lighting mode
7848                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7849                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7850                 else
7851                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7852         }
7853         if (rsurface.ent_flags & RENDER_ADDITIVE)
7854                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7855         else if (t->currentalpha < 1)
7856                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7857         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7858         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7859                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7860         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7861                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7862         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7863                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7864         if (t->backgroundnumskinframes)
7865                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7866         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7867         {
7868                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7869                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7870         }
7871         else
7872                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7873         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7874         {
7875                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7876                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7877         }
7878         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7879                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7880
7881         // there is no tcmod
7882         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7883         {
7884                 t->currenttexmatrix = r_waterscrollmatrix;
7885                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7886         }
7887         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7888         {
7889                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7890                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7891         }
7892
7893         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7894                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7895         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7896                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7897
7898         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7899         if (t->currentskinframe->qpixels)
7900                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7901         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7902         if (!t->basetexture)
7903                 t->basetexture = r_texture_notexture;
7904         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7905         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7906         t->nmaptexture = t->currentskinframe->nmap;
7907         if (!t->nmaptexture)
7908                 t->nmaptexture = r_texture_blanknormalmap;
7909         t->glosstexture = r_texture_black;
7910         t->glowtexture = t->currentskinframe->glow;
7911         t->fogtexture = t->currentskinframe->fog;
7912         t->reflectmasktexture = t->currentskinframe->reflect;
7913         if (t->backgroundnumskinframes)
7914         {
7915                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7916                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7917                 t->backgroundglosstexture = r_texture_black;
7918                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7919                 if (!t->backgroundnmaptexture)
7920                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7921                 // make sure that if glow is going to be used, both textures are not NULL
7922                 if (!t->backgroundglowtexture && t->glowtexture)
7923                         t->backgroundglowtexture = r_texture_black;
7924                 if (!t->glowtexture && t->backgroundglowtexture)
7925                         t->glowtexture = r_texture_black;
7926         }
7927         else
7928         {
7929                 t->backgroundbasetexture = r_texture_white;
7930                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7931                 t->backgroundglosstexture = r_texture_black;
7932                 t->backgroundglowtexture = NULL;
7933         }
7934         t->specularpower = r_shadow_glossexponent.value;
7935         // TODO: store reference values for these in the texture?
7936         t->specularscale = 0;
7937         if (r_shadow_gloss.integer > 0)
7938         {
7939                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7940                 {
7941                         if (r_shadow_glossintensity.value > 0)
7942                         {
7943                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7944                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7945                                 t->specularscale = r_shadow_glossintensity.value;
7946                         }
7947                 }
7948                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7949                 {
7950                         t->glosstexture = r_texture_white;
7951                         t->backgroundglosstexture = r_texture_white;
7952                         t->specularscale = r_shadow_gloss2intensity.value;
7953                         t->specularpower = r_shadow_gloss2exponent.value;
7954                 }
7955         }
7956         t->specularscale *= t->specularscalemod;
7957         t->specularpower *= t->specularpowermod;
7958         t->rtlightambient = 0;
7959
7960         // lightmaps mode looks bad with dlights using actual texturing, so turn
7961         // off the colormap and glossmap, but leave the normalmap on as it still
7962         // accurately represents the shading involved
7963         if (gl_lightmaps.integer)
7964         {
7965                 t->basetexture = r_texture_grey128;
7966                 t->pantstexture = r_texture_black;
7967                 t->shirttexture = r_texture_black;
7968                 t->nmaptexture = r_texture_blanknormalmap;
7969                 t->glosstexture = r_texture_black;
7970                 t->glowtexture = NULL;
7971                 t->fogtexture = NULL;
7972                 t->reflectmasktexture = NULL;
7973                 t->backgroundbasetexture = NULL;
7974                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7975                 t->backgroundglosstexture = r_texture_black;
7976                 t->backgroundglowtexture = NULL;
7977                 t->specularscale = 0;
7978                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7979         }
7980
7981         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7982         VectorClear(t->dlightcolor);
7983         t->currentnumlayers = 0;
7984         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7985         {
7986                 int blendfunc1, blendfunc2;
7987                 qboolean depthmask;
7988                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7989                 {
7990                         blendfunc1 = GL_SRC_ALPHA;
7991                         blendfunc2 = GL_ONE;
7992                 }
7993                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7994                 {
7995                         blendfunc1 = GL_SRC_ALPHA;
7996                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7997                 }
7998                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7999                 {
8000                         blendfunc1 = t->customblendfunc[0];
8001                         blendfunc2 = t->customblendfunc[1];
8002                 }
8003                 else
8004                 {
8005                         blendfunc1 = GL_ONE;
8006                         blendfunc2 = GL_ZERO;
8007                 }
8008                 // don't colormod evilblend textures
8009                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
8010                         VectorSet(t->lightmapcolor, 1, 1, 1);
8011                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
8012                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
8013                 {
8014                         // fullbright is not affected by r_refdef.lightmapintensity
8015                         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]);
8016                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8017                                 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]);
8018                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8019                                 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]);
8020                 }
8021                 else
8022                 {
8023                         vec3_t ambientcolor;
8024                         float colorscale;
8025                         // set the color tint used for lights affecting this surface
8026                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
8027                         colorscale = 2;
8028                         // q3bsp has no lightmap updates, so the lightstylevalue that
8029                         // would normally be baked into the lightmap must be
8030                         // applied to the color
8031                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
8032                         if (model->type == mod_brushq3)
8033                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
8034                         colorscale *= r_refdef.lightmapintensity;
8035                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
8036                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
8037                         // basic lit geometry
8038                         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]);
8039                         // add pants/shirt if needed
8040                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8041                                 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]);
8042                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8043                                 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]);
8044                         // now add ambient passes if needed
8045                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8046                         {
8047                                 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]);
8048                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8049                                         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]);
8050                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8051                                         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]);
8052                         }
8053                 }
8054                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8055                         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]);
8056                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8057                 {
8058                         // if this is opaque use alpha blend which will darken the earlier
8059                         // passes cheaply.
8060                         //
8061                         // if this is an alpha blended material, all the earlier passes
8062                         // were darkened by fog already, so we only need to add the fog
8063                         // color ontop through the fog mask texture
8064                         //
8065                         // if this is an additive blended material, all the earlier passes
8066                         // were darkened by fog already, and we should not add fog color
8067                         // (because the background was not darkened, there is no fog color
8068                         // that was lost behind it).
8069                         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]);
8070                 }
8071         }
8072
8073         return t->currentframe;
8074 }
8075
8076 rsurfacestate_t rsurface;
8077
8078 void RSurf_ActiveWorldEntity(void)
8079 {
8080         dp_model_t *model = r_refdef.scene.worldmodel;
8081         //if (rsurface.entity == r_refdef.scene.worldentity)
8082         //      return;
8083         rsurface.entity = r_refdef.scene.worldentity;
8084         rsurface.skeleton = NULL;
8085         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8086         rsurface.ent_skinnum = 0;
8087         rsurface.ent_qwskin = -1;
8088         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8089         rsurface.shadertime = r_refdef.scene.time;
8090         rsurface.matrix = identitymatrix;
8091         rsurface.inversematrix = identitymatrix;
8092         rsurface.matrixscale = 1;
8093         rsurface.inversematrixscale = 1;
8094         R_EntityMatrix(&identitymatrix);
8095         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8096         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8097         rsurface.fograngerecip = r_refdef.fograngerecip;
8098         rsurface.fogheightfade = r_refdef.fogheightfade;
8099         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8100         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8101         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8102         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8103         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8104         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8105         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8106         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8107         rsurface.colormod[3] = 1;
8108         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);
8109         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8110         rsurface.frameblend[0].lerp = 1;
8111         rsurface.ent_alttextures = false;
8112         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8113         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8114         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8115         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8116         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8117         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8118         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8119         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8120         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8121         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8122         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8123         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8124         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8125         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8126         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8127         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8128         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8129         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8130         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8131         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8132         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8133         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8134         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8135         rsurface.modelelement3i = model->surfmesh.data_element3i;
8136         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8137         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8138         rsurface.modelelement3s = model->surfmesh.data_element3s;
8139         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8140         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8141         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8142         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8143         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8144         rsurface.modelsurfaces = model->data_surfaces;
8145         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8146         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8147         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8148         rsurface.modelgeneratedvertex = false;
8149         rsurface.batchgeneratedvertex = false;
8150         rsurface.batchfirstvertex = 0;
8151         rsurface.batchnumvertices = 0;
8152         rsurface.batchfirsttriangle = 0;
8153         rsurface.batchnumtriangles = 0;
8154         rsurface.batchvertex3f  = NULL;
8155         rsurface.batchvertex3f_vertexbuffer = NULL;
8156         rsurface.batchvertex3f_bufferoffset = 0;
8157         rsurface.batchsvector3f = NULL;
8158         rsurface.batchsvector3f_vertexbuffer = NULL;
8159         rsurface.batchsvector3f_bufferoffset = 0;
8160         rsurface.batchtvector3f = NULL;
8161         rsurface.batchtvector3f_vertexbuffer = NULL;
8162         rsurface.batchtvector3f_bufferoffset = 0;
8163         rsurface.batchnormal3f  = NULL;
8164         rsurface.batchnormal3f_vertexbuffer = NULL;
8165         rsurface.batchnormal3f_bufferoffset = 0;
8166         rsurface.batchlightmapcolor4f = NULL;
8167         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8168         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8169         rsurface.batchtexcoordtexture2f = NULL;
8170         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8171         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8172         rsurface.batchtexcoordlightmap2f = NULL;
8173         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8174         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8175         rsurface.batchvertexmesh = NULL;
8176         rsurface.batchvertexmeshbuffer = NULL;
8177         rsurface.batchvertex3fbuffer = NULL;
8178         rsurface.batchelement3i = NULL;
8179         rsurface.batchelement3i_indexbuffer = NULL;
8180         rsurface.batchelement3i_bufferoffset = 0;
8181         rsurface.batchelement3s = NULL;
8182         rsurface.batchelement3s_indexbuffer = NULL;
8183         rsurface.batchelement3s_bufferoffset = 0;
8184         rsurface.passcolor4f = NULL;
8185         rsurface.passcolor4f_vertexbuffer = NULL;
8186         rsurface.passcolor4f_bufferoffset = 0;
8187         rsurface.forcecurrenttextureupdate = false;
8188 }
8189
8190 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8191 {
8192         dp_model_t *model = ent->model;
8193         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8194         //      return;
8195         rsurface.entity = (entity_render_t *)ent;
8196         rsurface.skeleton = ent->skeleton;
8197         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8198         rsurface.ent_skinnum = ent->skinnum;
8199         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;
8200         rsurface.ent_flags = ent->flags;
8201         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8202         rsurface.matrix = ent->matrix;
8203         rsurface.inversematrix = ent->inversematrix;
8204         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8205         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8206         R_EntityMatrix(&rsurface.matrix);
8207         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8208         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8209         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8210         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8211         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8212         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8213         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8214         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8215         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8216         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8217         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8218         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8219         rsurface.colormod[3] = ent->alpha;
8220         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8221         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8222         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8223         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8224         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8225         if (ent->model->brush.submodel && !prepass)
8226         {
8227                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8228                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8229         }
8230         if (model->surfmesh.isanimated && model->AnimateVertices)
8231         {
8232                 if (ent->animcache_vertex3f)
8233                 {
8234                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8235                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8236                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8237                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8238                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8239                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8240                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8241                 }
8242                 else if (wanttangents)
8243                 {
8244                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8245                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8246                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8247                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8248                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8249                         rsurface.modelvertexmesh = NULL;
8250                         rsurface.modelvertexmeshbuffer = NULL;
8251                         rsurface.modelvertex3fbuffer = NULL;
8252                 }
8253                 else if (wantnormals)
8254                 {
8255                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8256                         rsurface.modelsvector3f = NULL;
8257                         rsurface.modeltvector3f = NULL;
8258                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8259                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8260                         rsurface.modelvertexmesh = NULL;
8261                         rsurface.modelvertexmeshbuffer = NULL;
8262                         rsurface.modelvertex3fbuffer = NULL;
8263                 }
8264                 else
8265                 {
8266                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8267                         rsurface.modelsvector3f = NULL;
8268                         rsurface.modeltvector3f = NULL;
8269                         rsurface.modelnormal3f = NULL;
8270                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8271                         rsurface.modelvertexmesh = NULL;
8272                         rsurface.modelvertexmeshbuffer = NULL;
8273                         rsurface.modelvertex3fbuffer = NULL;
8274                 }
8275                 rsurface.modelvertex3f_vertexbuffer = 0;
8276                 rsurface.modelvertex3f_bufferoffset = 0;
8277                 rsurface.modelsvector3f_vertexbuffer = 0;
8278                 rsurface.modelsvector3f_bufferoffset = 0;
8279                 rsurface.modeltvector3f_vertexbuffer = 0;
8280                 rsurface.modeltvector3f_bufferoffset = 0;
8281                 rsurface.modelnormal3f_vertexbuffer = 0;
8282                 rsurface.modelnormal3f_bufferoffset = 0;
8283                 rsurface.modelgeneratedvertex = true;
8284         }
8285         else
8286         {
8287                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8288                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8289                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8290                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8291                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8292                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8293                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8294                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8295                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8296                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8297                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8298                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8299                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8300                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8301                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8302                 rsurface.modelgeneratedvertex = false;
8303         }
8304         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8305         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8306         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8307         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8308         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8309         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8310         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8311         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8312         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8313         rsurface.modelelement3i = model->surfmesh.data_element3i;
8314         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8315         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8316         rsurface.modelelement3s = model->surfmesh.data_element3s;
8317         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8318         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8319         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8320         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8321         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8322         rsurface.modelsurfaces = model->data_surfaces;
8323         rsurface.batchgeneratedvertex = false;
8324         rsurface.batchfirstvertex = 0;
8325         rsurface.batchnumvertices = 0;
8326         rsurface.batchfirsttriangle = 0;
8327         rsurface.batchnumtriangles = 0;
8328         rsurface.batchvertex3f  = NULL;
8329         rsurface.batchvertex3f_vertexbuffer = NULL;
8330         rsurface.batchvertex3f_bufferoffset = 0;
8331         rsurface.batchsvector3f = NULL;
8332         rsurface.batchsvector3f_vertexbuffer = NULL;
8333         rsurface.batchsvector3f_bufferoffset = 0;
8334         rsurface.batchtvector3f = NULL;
8335         rsurface.batchtvector3f_vertexbuffer = NULL;
8336         rsurface.batchtvector3f_bufferoffset = 0;
8337         rsurface.batchnormal3f  = NULL;
8338         rsurface.batchnormal3f_vertexbuffer = NULL;
8339         rsurface.batchnormal3f_bufferoffset = 0;
8340         rsurface.batchlightmapcolor4f = NULL;
8341         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8342         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8343         rsurface.batchtexcoordtexture2f = NULL;
8344         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8345         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8346         rsurface.batchtexcoordlightmap2f = NULL;
8347         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8348         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8349         rsurface.batchvertexmesh = NULL;
8350         rsurface.batchvertexmeshbuffer = NULL;
8351         rsurface.batchvertex3fbuffer = NULL;
8352         rsurface.batchelement3i = NULL;
8353         rsurface.batchelement3i_indexbuffer = NULL;
8354         rsurface.batchelement3i_bufferoffset = 0;
8355         rsurface.batchelement3s = NULL;
8356         rsurface.batchelement3s_indexbuffer = NULL;
8357         rsurface.batchelement3s_bufferoffset = 0;
8358         rsurface.passcolor4f = NULL;
8359         rsurface.passcolor4f_vertexbuffer = NULL;
8360         rsurface.passcolor4f_bufferoffset = 0;
8361         rsurface.forcecurrenttextureupdate = false;
8362 }
8363
8364 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)
8365 {
8366         rsurface.entity = r_refdef.scene.worldentity;
8367         rsurface.skeleton = NULL;
8368         rsurface.ent_skinnum = 0;
8369         rsurface.ent_qwskin = -1;
8370         rsurface.ent_flags = entflags;
8371         rsurface.shadertime = r_refdef.scene.time - shadertime;
8372         rsurface.modelnumvertices = numvertices;
8373         rsurface.modelnumtriangles = numtriangles;
8374         rsurface.matrix = *matrix;
8375         rsurface.inversematrix = *inversematrix;
8376         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8377         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8378         R_EntityMatrix(&rsurface.matrix);
8379         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8380         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8381         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8382         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8383         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8384         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8385         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8386         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8387         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8388         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8389         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8390         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8391         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);
8392         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8393         rsurface.frameblend[0].lerp = 1;
8394         rsurface.ent_alttextures = false;
8395         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8396         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8397         if (wanttangents)
8398         {
8399                 rsurface.modelvertex3f = (float *)vertex3f;
8400                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8401                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8402                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8403         }
8404         else if (wantnormals)
8405         {
8406                 rsurface.modelvertex3f = (float *)vertex3f;
8407                 rsurface.modelsvector3f = NULL;
8408                 rsurface.modeltvector3f = NULL;
8409                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8410         }
8411         else
8412         {
8413                 rsurface.modelvertex3f = (float *)vertex3f;
8414                 rsurface.modelsvector3f = NULL;
8415                 rsurface.modeltvector3f = NULL;
8416                 rsurface.modelnormal3f = NULL;
8417         }
8418         rsurface.modelvertexmesh = NULL;
8419         rsurface.modelvertexmeshbuffer = NULL;
8420         rsurface.modelvertex3fbuffer = NULL;
8421         rsurface.modelvertex3f_vertexbuffer = 0;
8422         rsurface.modelvertex3f_bufferoffset = 0;
8423         rsurface.modelsvector3f_vertexbuffer = 0;
8424         rsurface.modelsvector3f_bufferoffset = 0;
8425         rsurface.modeltvector3f_vertexbuffer = 0;
8426         rsurface.modeltvector3f_bufferoffset = 0;
8427         rsurface.modelnormal3f_vertexbuffer = 0;
8428         rsurface.modelnormal3f_bufferoffset = 0;
8429         rsurface.modelgeneratedvertex = true;
8430         rsurface.modellightmapcolor4f  = (float *)color4f;
8431         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8432         rsurface.modellightmapcolor4f_bufferoffset = 0;
8433         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8434         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8435         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8436         rsurface.modeltexcoordlightmap2f  = NULL;
8437         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8438         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8439         rsurface.modelelement3i = (int *)element3i;
8440         rsurface.modelelement3i_indexbuffer = NULL;
8441         rsurface.modelelement3i_bufferoffset = 0;
8442         rsurface.modelelement3s = (unsigned short *)element3s;
8443         rsurface.modelelement3s_indexbuffer = NULL;
8444         rsurface.modelelement3s_bufferoffset = 0;
8445         rsurface.modellightmapoffsets = NULL;
8446         rsurface.modelsurfaces = NULL;
8447         rsurface.batchgeneratedvertex = false;
8448         rsurface.batchfirstvertex = 0;
8449         rsurface.batchnumvertices = 0;
8450         rsurface.batchfirsttriangle = 0;
8451         rsurface.batchnumtriangles = 0;
8452         rsurface.batchvertex3f  = NULL;
8453         rsurface.batchvertex3f_vertexbuffer = NULL;
8454         rsurface.batchvertex3f_bufferoffset = 0;
8455         rsurface.batchsvector3f = NULL;
8456         rsurface.batchsvector3f_vertexbuffer = NULL;
8457         rsurface.batchsvector3f_bufferoffset = 0;
8458         rsurface.batchtvector3f = NULL;
8459         rsurface.batchtvector3f_vertexbuffer = NULL;
8460         rsurface.batchtvector3f_bufferoffset = 0;
8461         rsurface.batchnormal3f  = NULL;
8462         rsurface.batchnormal3f_vertexbuffer = NULL;
8463         rsurface.batchnormal3f_bufferoffset = 0;
8464         rsurface.batchlightmapcolor4f = NULL;
8465         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8466         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8467         rsurface.batchtexcoordtexture2f = NULL;
8468         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8469         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8470         rsurface.batchtexcoordlightmap2f = NULL;
8471         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8472         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8473         rsurface.batchvertexmesh = NULL;
8474         rsurface.batchvertexmeshbuffer = NULL;
8475         rsurface.batchvertex3fbuffer = NULL;
8476         rsurface.batchelement3i = NULL;
8477         rsurface.batchelement3i_indexbuffer = NULL;
8478         rsurface.batchelement3i_bufferoffset = 0;
8479         rsurface.batchelement3s = NULL;
8480         rsurface.batchelement3s_indexbuffer = NULL;
8481         rsurface.batchelement3s_bufferoffset = 0;
8482         rsurface.passcolor4f = NULL;
8483         rsurface.passcolor4f_vertexbuffer = NULL;
8484         rsurface.passcolor4f_bufferoffset = 0;
8485         rsurface.forcecurrenttextureupdate = true;
8486
8487         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8488         {
8489                 if ((wantnormals || wanttangents) && !normal3f)
8490                 {
8491                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8492                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8493                 }
8494                 if (wanttangents && !svector3f)
8495                 {
8496                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8497                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8498                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8499                 }
8500         }
8501 }
8502
8503 float RSurf_FogPoint(const float *v)
8504 {
8505         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8506         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8507         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8508         float FogHeightFade = r_refdef.fogheightfade;
8509         float fogfrac;
8510         unsigned int fogmasktableindex;
8511         if (r_refdef.fogplaneviewabove)
8512                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8513         else
8514                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8515         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8516         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8517 }
8518
8519 float RSurf_FogVertex(const float *v)
8520 {
8521         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8522         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8523         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8524         float FogHeightFade = rsurface.fogheightfade;
8525         float fogfrac;
8526         unsigned int fogmasktableindex;
8527         if (r_refdef.fogplaneviewabove)
8528                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8529         else
8530                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8531         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8532         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8533 }
8534
8535 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8536 {
8537         int i;
8538         for (i = 0;i < numelements;i++)
8539                 outelement3i[i] = inelement3i[i] + adjust;
8540 }
8541
8542 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8543 extern cvar_t gl_vbo;
8544 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8545 {
8546         int deformindex;
8547         int firsttriangle;
8548         int numtriangles;
8549         int firstvertex;
8550         int endvertex;
8551         int numvertices;
8552         int surfacefirsttriangle;
8553         int surfacenumtriangles;
8554         int surfacefirstvertex;
8555         int surfaceendvertex;
8556         int surfacenumvertices;
8557         int batchnumvertices;
8558         int batchnumtriangles;
8559         int needsupdate;
8560         int i, j;
8561         qboolean gaps;
8562         qboolean dynamicvertex;
8563         float amplitude;
8564         float animpos;
8565         float scale;
8566         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8567         float waveparms[4];
8568         q3shaderinfo_deform_t *deform;
8569         const msurface_t *surface, *firstsurface;
8570         r_vertexmesh_t *vertexmesh;
8571         if (!texturenumsurfaces)
8572                 return;
8573         // find vertex range of this surface batch
8574         gaps = false;
8575         firstsurface = texturesurfacelist[0];
8576         firsttriangle = firstsurface->num_firsttriangle;
8577         batchnumvertices = 0;
8578         batchnumtriangles = 0;
8579         firstvertex = endvertex = firstsurface->num_firstvertex;
8580         for (i = 0;i < texturenumsurfaces;i++)
8581         {
8582                 surface = texturesurfacelist[i];
8583                 if (surface != firstsurface + i)
8584                         gaps = true;
8585                 surfacefirstvertex = surface->num_firstvertex;
8586                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8587                 surfacenumvertices = surface->num_vertices;
8588                 surfacenumtriangles = surface->num_triangles;
8589                 if (firstvertex > surfacefirstvertex)
8590                         firstvertex = surfacefirstvertex;
8591                 if (endvertex < surfaceendvertex)
8592                         endvertex = surfaceendvertex;
8593                 batchnumvertices += surfacenumvertices;
8594                 batchnumtriangles += surfacenumtriangles;
8595         }
8596
8597         // we now know the vertex range used, and if there are any gaps in it
8598         rsurface.batchfirstvertex = firstvertex;
8599         rsurface.batchnumvertices = endvertex - firstvertex;
8600         rsurface.batchfirsttriangle = firsttriangle;
8601         rsurface.batchnumtriangles = batchnumtriangles;
8602
8603         // this variable holds flags for which properties have been updated that
8604         // may require regenerating vertexmesh array...
8605         needsupdate = 0;
8606
8607         // check if any dynamic vertex processing must occur
8608         dynamicvertex = false;
8609
8610         // if there is a chance of animated vertex colors, it's a dynamic batch
8611         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8612         {
8613                 dynamicvertex = true;
8614                 batchneed |= BATCHNEED_NOGAPS;
8615                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8616         }
8617
8618         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8619         {
8620                 switch (deform->deform)
8621                 {
8622                 default:
8623                 case Q3DEFORM_PROJECTIONSHADOW:
8624                 case Q3DEFORM_TEXT0:
8625                 case Q3DEFORM_TEXT1:
8626                 case Q3DEFORM_TEXT2:
8627                 case Q3DEFORM_TEXT3:
8628                 case Q3DEFORM_TEXT4:
8629                 case Q3DEFORM_TEXT5:
8630                 case Q3DEFORM_TEXT6:
8631                 case Q3DEFORM_TEXT7:
8632                 case Q3DEFORM_NONE:
8633                         break;
8634                 case Q3DEFORM_AUTOSPRITE:
8635                         dynamicvertex = true;
8636                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8637                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8638                         break;
8639                 case Q3DEFORM_AUTOSPRITE2:
8640                         dynamicvertex = true;
8641                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8642                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8643                         break;
8644                 case Q3DEFORM_NORMAL:
8645                         dynamicvertex = true;
8646                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8647                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8648                         break;
8649                 case Q3DEFORM_WAVE:
8650                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8651                                 break; // if wavefunc is a nop, ignore this transform
8652                         dynamicvertex = true;
8653                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8654                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8655                         break;
8656                 case Q3DEFORM_BULGE:
8657                         dynamicvertex = true;
8658                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8659                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8660                         break;
8661                 case Q3DEFORM_MOVE:
8662                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8663                                 break; // if wavefunc is a nop, ignore this transform
8664                         dynamicvertex = true;
8665                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8666                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8667                         break;
8668                 }
8669         }
8670         switch(rsurface.texture->tcgen.tcgen)
8671         {
8672         default:
8673         case Q3TCGEN_TEXTURE:
8674                 break;
8675         case Q3TCGEN_LIGHTMAP:
8676                 dynamicvertex = true;
8677                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8678                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8679                 break;
8680         case Q3TCGEN_VECTOR:
8681                 dynamicvertex = true;
8682                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8683                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8684                 break;
8685         case Q3TCGEN_ENVIRONMENT:
8686                 dynamicvertex = true;
8687                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8688                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8689                 break;
8690         }
8691         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8692         {
8693                 dynamicvertex = true;
8694                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8695                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8696         }
8697
8698         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8699         {
8700                 dynamicvertex = true;
8701                 batchneed |= BATCHNEED_NOGAPS;
8702                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8703         }
8704
8705         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8706         {
8707                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8708                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8709                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8710                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8711                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8712                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8713                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8714         }
8715
8716         // when the model data has no vertex buffer (dynamic mesh), we need to
8717         // eliminate gaps
8718         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8719                 batchneed |= BATCHNEED_NOGAPS;
8720
8721         // if needsupdate, we have to do a dynamic vertex batch for sure
8722         if (needsupdate & batchneed)
8723                 dynamicvertex = true;
8724
8725         // see if we need to build vertexmesh from arrays
8726         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8727                 dynamicvertex = true;
8728
8729         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8730         // also some drivers strongly dislike firstvertex
8731         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8732                 dynamicvertex = true;
8733
8734         rsurface.batchvertex3f = rsurface.modelvertex3f;
8735         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8736         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8737         rsurface.batchsvector3f = rsurface.modelsvector3f;
8738         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8739         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8740         rsurface.batchtvector3f = rsurface.modeltvector3f;
8741         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8742         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8743         rsurface.batchnormal3f = rsurface.modelnormal3f;
8744         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8745         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8746         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8747         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8748         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8749         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8750         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8751         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8752         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8753         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8754         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8755         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8756         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8757         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8758         rsurface.batchelement3i = rsurface.modelelement3i;
8759         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8760         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8761         rsurface.batchelement3s = rsurface.modelelement3s;
8762         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8763         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8764
8765         // if any dynamic vertex processing has to occur in software, we copy the
8766         // entire surface list together before processing to rebase the vertices
8767         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8768         //
8769         // if any gaps exist and we do not have a static vertex buffer, we have to
8770         // copy the surface list together to avoid wasting upload bandwidth on the
8771         // vertices in the gaps.
8772         //
8773         // if gaps exist and we have a static vertex buffer, we still have to
8774         // combine the index buffer ranges into one dynamic index buffer.
8775         //
8776         // in all cases we end up with data that can be drawn in one call.
8777
8778         if (!dynamicvertex)
8779         {
8780                 // static vertex data, just set pointers...
8781                 rsurface.batchgeneratedvertex = false;
8782                 // if there are gaps, we want to build a combined index buffer,
8783                 // otherwise use the original static buffer with an appropriate offset
8784                 if (gaps)
8785                 {
8786                         // build a new triangle elements array for this batch
8787                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8788                         rsurface.batchfirsttriangle = 0;
8789                         numtriangles = 0;
8790                         for (i = 0;i < texturenumsurfaces;i++)
8791                         {
8792                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8793                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8794                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8795                                 numtriangles += surfacenumtriangles;
8796                         }
8797                         rsurface.batchelement3i_indexbuffer = NULL;
8798                         rsurface.batchelement3i_bufferoffset = 0;
8799                         rsurface.batchelement3s = NULL;
8800                         rsurface.batchelement3s_indexbuffer = NULL;
8801                         rsurface.batchelement3s_bufferoffset = 0;
8802                         if (endvertex <= 65536)
8803                         {
8804                                 // make a 16bit (unsigned short) index array if possible
8805                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8806                                 for (i = 0;i < numtriangles*3;i++)
8807                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8808                         }
8809                 }
8810                 return;
8811         }
8812
8813         // something needs software processing, do it for real...
8814         // we only directly handle separate array data in this case and then
8815         // generate interleaved data if needed...
8816         rsurface.batchgeneratedvertex = true;
8817
8818         // now copy the vertex data into a combined array and make an index array
8819         // (this is what Quake3 does all the time)
8820         //if (gaps || rsurface.batchfirstvertex)
8821         {
8822                 rsurface.batchvertex3fbuffer = NULL;
8823                 rsurface.batchvertexmesh = NULL;
8824                 rsurface.batchvertexmeshbuffer = NULL;
8825                 rsurface.batchvertex3f = NULL;
8826                 rsurface.batchvertex3f_vertexbuffer = NULL;
8827                 rsurface.batchvertex3f_bufferoffset = 0;
8828                 rsurface.batchsvector3f = NULL;
8829                 rsurface.batchsvector3f_vertexbuffer = NULL;
8830                 rsurface.batchsvector3f_bufferoffset = 0;
8831                 rsurface.batchtvector3f = NULL;
8832                 rsurface.batchtvector3f_vertexbuffer = NULL;
8833                 rsurface.batchtvector3f_bufferoffset = 0;
8834                 rsurface.batchnormal3f = NULL;
8835                 rsurface.batchnormal3f_vertexbuffer = NULL;
8836                 rsurface.batchnormal3f_bufferoffset = 0;
8837                 rsurface.batchlightmapcolor4f = NULL;
8838                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8839                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8840                 rsurface.batchtexcoordtexture2f = NULL;
8841                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8842                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8843                 rsurface.batchtexcoordlightmap2f = NULL;
8844                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8845                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8846                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8847                 rsurface.batchelement3i_indexbuffer = NULL;
8848                 rsurface.batchelement3i_bufferoffset = 0;
8849                 rsurface.batchelement3s = NULL;
8850                 rsurface.batchelement3s_indexbuffer = NULL;
8851                 rsurface.batchelement3s_bufferoffset = 0;
8852                 // we'll only be setting up certain arrays as needed
8853                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8854                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8855                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8856                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8857                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8858                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8859                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8860                 {
8861                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8862                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8863                 }
8864                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8865                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8866                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8867                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8868                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8869                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8870                 numvertices = 0;
8871                 numtriangles = 0;
8872                 for (i = 0;i < texturenumsurfaces;i++)
8873                 {
8874                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8875                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8876                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8877                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8878                         // copy only the data requested
8879                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8880                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8881                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8882                         {
8883                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8884                                 {
8885                                         if (rsurface.batchvertex3f)
8886                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8887                                         else
8888                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8889                                 }
8890                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8891                                 {
8892                                         if (rsurface.modelnormal3f)
8893                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8894                                         else
8895                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8896                                 }
8897                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8898                                 {
8899                                         if (rsurface.modelsvector3f)
8900                                         {
8901                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8902                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8903                                         }
8904                                         else
8905                                         {
8906                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8907                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8908                                         }
8909                                 }
8910                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8911                                 {
8912                                         if (rsurface.modellightmapcolor4f)
8913                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8914                                         else
8915                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8916                                 }
8917                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8918                                 {
8919                                         if (rsurface.modeltexcoordtexture2f)
8920                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8921                                         else
8922                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8923                                 }
8924                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8925                                 {
8926                                         if (rsurface.modeltexcoordlightmap2f)
8927                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8928                                         else
8929                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8930                                 }
8931                         }
8932                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8933                         numvertices += surfacenumvertices;
8934                         numtriangles += surfacenumtriangles;
8935                 }
8936
8937                 // generate a 16bit index array as well if possible
8938                 // (in general, dynamic batches fit)
8939                 if (numvertices <= 65536)
8940                 {
8941                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8942                         for (i = 0;i < numtriangles*3;i++)
8943                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8944                 }
8945
8946                 // since we've copied everything, the batch now starts at 0
8947                 rsurface.batchfirstvertex = 0;
8948                 rsurface.batchnumvertices = batchnumvertices;
8949                 rsurface.batchfirsttriangle = 0;
8950                 rsurface.batchnumtriangles = batchnumtriangles;
8951         }
8952
8953         // q1bsp surfaces rendered in vertex color mode have to have colors
8954         // calculated based on lightstyles
8955         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8956         {
8957                 // generate color arrays for the surfaces in this list
8958                 int c[4];
8959                 int scale;
8960                 int size3;
8961                 const int *offsets;
8962                 const unsigned char *lm;
8963                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8964                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8965                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8966                 numvertices = 0;
8967                 for (i = 0;i < texturenumsurfaces;i++)
8968                 {
8969                         surface = texturesurfacelist[i];
8970                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8971                         surfacenumvertices = surface->num_vertices;
8972                         if (surface->lightmapinfo->samples)
8973                         {
8974                                 for (j = 0;j < surfacenumvertices;j++)
8975                                 {
8976                                         lm = surface->lightmapinfo->samples + offsets[j];
8977                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8978                                         VectorScale(lm, scale, c);
8979                                         if (surface->lightmapinfo->styles[1] != 255)
8980                                         {
8981                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8982                                                 lm += size3;
8983                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8984                                                 VectorMA(c, scale, lm, c);
8985                                                 if (surface->lightmapinfo->styles[2] != 255)
8986                                                 {
8987                                                         lm += size3;
8988                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8989                                                         VectorMA(c, scale, lm, c);
8990                                                         if (surface->lightmapinfo->styles[3] != 255)
8991                                                         {
8992                                                                 lm += size3;
8993                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8994                                                                 VectorMA(c, scale, lm, c);
8995                                                         }
8996                                                 }
8997                                         }
8998                                         c[0] >>= 7;
8999                                         c[1] >>= 7;
9000                                         c[2] >>= 7;
9001                                         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);
9002                                         numvertices++;
9003                                 }
9004                         }
9005                         else
9006                         {
9007                                 for (j = 0;j < surfacenumvertices;j++)
9008                                 {
9009                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
9010                                         numvertices++;
9011                                 }
9012                         }
9013                 }
9014         }
9015
9016         // if vertices are deformed (sprite flares and things in maps, possibly
9017         // water waves, bulges and other deformations), modify the copied vertices
9018         // in place
9019         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
9020         {
9021                 switch (deform->deform)
9022                 {
9023                 default:
9024                 case Q3DEFORM_PROJECTIONSHADOW:
9025                 case Q3DEFORM_TEXT0:
9026                 case Q3DEFORM_TEXT1:
9027                 case Q3DEFORM_TEXT2:
9028                 case Q3DEFORM_TEXT3:
9029                 case Q3DEFORM_TEXT4:
9030                 case Q3DEFORM_TEXT5:
9031                 case Q3DEFORM_TEXT6:
9032                 case Q3DEFORM_TEXT7:
9033                 case Q3DEFORM_NONE:
9034                         break;
9035                 case Q3DEFORM_AUTOSPRITE:
9036                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9037                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9038                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9039                         VectorNormalize(newforward);
9040                         VectorNormalize(newright);
9041                         VectorNormalize(newup);
9042 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9043 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9044 //                      rsurface.batchvertex3f_bufferoffset = 0;
9045 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9046 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9047 //                      rsurface.batchsvector3f_bufferoffset = 0;
9048 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9049 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9050 //                      rsurface.batchtvector3f_bufferoffset = 0;
9051 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9052 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9053 //                      rsurface.batchnormal3f_bufferoffset = 0;
9054                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9055                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9056                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9057                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9058                                 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);
9059                         // a single autosprite surface can contain multiple sprites...
9060                         for (j = 0;j < batchnumvertices - 3;j += 4)
9061                         {
9062                                 VectorClear(center);
9063                                 for (i = 0;i < 4;i++)
9064                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9065                                 VectorScale(center, 0.25f, center);
9066                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9067                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9068                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9069                                 for (i = 0;i < 4;i++)
9070                                 {
9071                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9072                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9073                                 }
9074                         }
9075                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9076                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9077                         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);
9078                         break;
9079                 case Q3DEFORM_AUTOSPRITE2:
9080                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9081                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9082                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9083                         VectorNormalize(newforward);
9084                         VectorNormalize(newright);
9085                         VectorNormalize(newup);
9086 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9087 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9088 //                      rsurface.batchvertex3f_bufferoffset = 0;
9089                         {
9090                                 const float *v1, *v2;
9091                                 vec3_t start, end;
9092                                 float f, l;
9093                                 struct
9094                                 {
9095                                         float length2;
9096                                         const float *v1;
9097                                         const float *v2;
9098                                 }
9099                                 shortest[2];
9100                                 memset(shortest, 0, sizeof(shortest));
9101                                 // a single autosprite surface can contain multiple sprites...
9102                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9103                                 {
9104                                         VectorClear(center);
9105                                         for (i = 0;i < 4;i++)
9106                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9107                                         VectorScale(center, 0.25f, center);
9108                                         // find the two shortest edges, then use them to define the
9109                                         // axis vectors for rotating around the central axis
9110                                         for (i = 0;i < 6;i++)
9111                                         {
9112                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9113                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9114                                                 l = VectorDistance2(v1, v2);
9115                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9116                                                 if (v1[2] != v2[2])
9117                                                         l += (1.0f / 1024.0f);
9118                                                 if (shortest[0].length2 > l || i == 0)
9119                                                 {
9120                                                         shortest[1] = shortest[0];
9121                                                         shortest[0].length2 = l;
9122                                                         shortest[0].v1 = v1;
9123                                                         shortest[0].v2 = v2;
9124                                                 }
9125                                                 else if (shortest[1].length2 > l || i == 1)
9126                                                 {
9127                                                         shortest[1].length2 = l;
9128                                                         shortest[1].v1 = v1;
9129                                                         shortest[1].v2 = v2;
9130                                                 }
9131                                         }
9132                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9133                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9134                                         // this calculates the right vector from the shortest edge
9135                                         // and the up vector from the edge midpoints
9136                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9137                                         VectorNormalize(right);
9138                                         VectorSubtract(end, start, up);
9139                                         VectorNormalize(up);
9140                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9141                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9142                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9143                                         VectorNegate(forward, forward);
9144                                         VectorReflect(forward, 0, up, forward);
9145                                         VectorNormalize(forward);
9146                                         CrossProduct(up, forward, newright);
9147                                         VectorNormalize(newright);
9148                                         // rotate the quad around the up axis vector, this is made
9149                                         // especially easy by the fact we know the quad is flat,
9150                                         // so we only have to subtract the center position and
9151                                         // measure distance along the right vector, and then
9152                                         // multiply that by the newright vector and add back the
9153                                         // center position
9154                                         // we also need to subtract the old position to undo the
9155                                         // displacement from the center, which we do with a
9156                                         // DotProduct, the subtraction/addition of center is also
9157                                         // optimized into DotProducts here
9158                                         l = DotProduct(right, center);
9159                                         for (i = 0;i < 4;i++)
9160                                         {
9161                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9162                                                 f = DotProduct(right, v1) - l;
9163                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9164                                         }
9165                                 }
9166                         }
9167                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9168                         {
9169 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9170 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9171 //                              rsurface.batchnormal3f_bufferoffset = 0;
9172                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9173                         }
9174                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9175                         {
9176 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9177 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9178 //                              rsurface.batchsvector3f_bufferoffset = 0;
9179 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9180 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9181 //                              rsurface.batchtvector3f_bufferoffset = 0;
9182                                 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);
9183                         }
9184                         break;
9185                 case Q3DEFORM_NORMAL:
9186                         // deform the normals to make reflections wavey
9187                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9188                         rsurface.batchnormal3f_vertexbuffer = NULL;
9189                         rsurface.batchnormal3f_bufferoffset = 0;
9190                         for (j = 0;j < batchnumvertices;j++)
9191                         {
9192                                 float vertex[3];
9193                                 float *normal = rsurface.batchnormal3f + 3*j;
9194                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9195                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9196                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9197                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9198                                 VectorNormalize(normal);
9199                         }
9200                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9201                         {
9202 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9203 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9204 //                              rsurface.batchsvector3f_bufferoffset = 0;
9205 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9206 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9207 //                              rsurface.batchtvector3f_bufferoffset = 0;
9208                                 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);
9209                         }
9210                         break;
9211                 case Q3DEFORM_WAVE:
9212                         // deform vertex array to make wavey water and flags and such
9213                         waveparms[0] = deform->waveparms[0];
9214                         waveparms[1] = deform->waveparms[1];
9215                         waveparms[2] = deform->waveparms[2];
9216                         waveparms[3] = deform->waveparms[3];
9217                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9218                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9219                         // this is how a divisor of vertex influence on deformation
9220                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9221                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9222 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9223 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9224 //                      rsurface.batchvertex3f_bufferoffset = 0;
9225 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9226 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9227 //                      rsurface.batchnormal3f_bufferoffset = 0;
9228                         for (j = 0;j < batchnumvertices;j++)
9229                         {
9230                                 // if the wavefunc depends on time, evaluate it per-vertex
9231                                 if (waveparms[3])
9232                                 {
9233                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9234                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9235                                 }
9236                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9237                         }
9238                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9239                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9240                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9241                         {
9242 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9243 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9244 //                              rsurface.batchsvector3f_bufferoffset = 0;
9245 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9246 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9247 //                              rsurface.batchtvector3f_bufferoffset = 0;
9248                                 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);
9249                         }
9250                         break;
9251                 case Q3DEFORM_BULGE:
9252                         // deform vertex array to make the surface have moving bulges
9253 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9254 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9255 //                      rsurface.batchvertex3f_bufferoffset = 0;
9256 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9257 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9258 //                      rsurface.batchnormal3f_bufferoffset = 0;
9259                         for (j = 0;j < batchnumvertices;j++)
9260                         {
9261                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9262                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9263                         }
9264                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9265                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9266                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9267                         {
9268 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9269 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9270 //                              rsurface.batchsvector3f_bufferoffset = 0;
9271 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9272 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9273 //                              rsurface.batchtvector3f_bufferoffset = 0;
9274                                 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);
9275                         }
9276                         break;
9277                 case Q3DEFORM_MOVE:
9278                         // deform vertex array
9279                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9280                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9281                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9282                         VectorScale(deform->parms, scale, waveparms);
9283 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9284 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9285 //                      rsurface.batchvertex3f_bufferoffset = 0;
9286                         for (j = 0;j < batchnumvertices;j++)
9287                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9288                         break;
9289                 }
9290         }
9291
9292         // generate texcoords based on the chosen texcoord source
9293         switch(rsurface.texture->tcgen.tcgen)
9294         {
9295         default:
9296         case Q3TCGEN_TEXTURE:
9297                 break;
9298         case Q3TCGEN_LIGHTMAP:
9299 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9300 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9301 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9302                 if (rsurface.batchtexcoordlightmap2f)
9303                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9304                 break;
9305         case Q3TCGEN_VECTOR:
9306 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9307 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9308 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9309                 for (j = 0;j < batchnumvertices;j++)
9310                 {
9311                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9312                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9313                 }
9314                 break;
9315         case Q3TCGEN_ENVIRONMENT:
9316                 // make environment reflections using a spheremap
9317                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9318                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9319                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9320                 for (j = 0;j < batchnumvertices;j++)
9321                 {
9322                         // identical to Q3A's method, but executed in worldspace so
9323                         // carried models can be shiny too
9324
9325                         float viewer[3], d, reflected[3], worldreflected[3];
9326
9327                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9328                         // VectorNormalize(viewer);
9329
9330                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9331
9332                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9333                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9334                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9335                         // note: this is proportinal to viewer, so we can normalize later
9336
9337                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9338                         VectorNormalize(worldreflected);
9339
9340                         // note: this sphere map only uses world x and z!
9341                         // so positive and negative y will LOOK THE SAME.
9342                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9343                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9344                 }
9345                 break;
9346         }
9347         // the only tcmod that needs software vertex processing is turbulent, so
9348         // check for it here and apply the changes if needed
9349         // and we only support that as the first one
9350         // (handling a mixture of turbulent and other tcmods would be problematic
9351         //  without punting it entirely to a software path)
9352         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9353         {
9354                 amplitude = rsurface.texture->tcmods[0].parms[1];
9355                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9356 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9357 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9358 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9359                 for (j = 0;j < batchnumvertices;j++)
9360                 {
9361                         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);
9362                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9363                 }
9364         }
9365
9366         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9367         {
9368                 // convert the modified arrays to vertex structs
9369 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9370 //              rsurface.batchvertexmeshbuffer = NULL;
9371                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9372                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9373                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9374                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9375                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9376                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9377                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9378                 {
9379                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9380                         {
9381                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9382                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9383                         }
9384                 }
9385                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9386                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9387                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9388                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9389                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9390                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9391                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9392                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9393                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9394         }
9395 }
9396
9397 void RSurf_DrawBatch(void)
9398 {
9399         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9400         // through the pipeline, killing it earlier in the pipeline would have
9401         // per-surface overhead rather than per-batch overhead, so it's best to
9402         // reject it here, before it hits glDraw.
9403         if (rsurface.batchnumtriangles == 0)
9404                 return;
9405 #if 0
9406         // batch debugging code
9407         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9408         {
9409                 int i;
9410                 int j;
9411                 int c;
9412                 const int *e;
9413                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9414                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9415                 {
9416                         c = e[i];
9417                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9418                         {
9419                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9420                                 {
9421                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9422                                                 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);
9423                                         break;
9424                                 }
9425                         }
9426                 }
9427         }
9428 #endif
9429         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);
9430 }
9431
9432 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9433 {
9434         // pick the closest matching water plane
9435         int planeindex, vertexindex, bestplaneindex = -1;
9436         float d, bestd;
9437         vec3_t vert;
9438         const float *v;
9439         r_waterstate_waterplane_t *p;
9440         qboolean prepared = false;
9441         bestd = 0;
9442         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9443         {
9444                 if(p->camera_entity != rsurface.texture->camera_entity)
9445                         continue;
9446                 d = 0;
9447                 if(!prepared)
9448                 {
9449                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9450                         prepared = true;
9451                         if(rsurface.batchnumvertices == 0)
9452                                 break;
9453                 }
9454                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9455                 {
9456                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9457                         d += fabs(PlaneDiff(vert, &p->plane));
9458                 }
9459                 if (bestd > d || bestplaneindex < 0)
9460                 {
9461                         bestd = d;
9462                         bestplaneindex = planeindex;
9463                 }
9464         }
9465         return bestplaneindex;
9466         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9467         // this situation though, as it might be better to render single larger
9468         // batches with useless stuff (backface culled for example) than to
9469         // render multiple smaller batches
9470 }
9471
9472 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9473 {
9474         int i;
9475         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9476         rsurface.passcolor4f_vertexbuffer = 0;
9477         rsurface.passcolor4f_bufferoffset = 0;
9478         for (i = 0;i < rsurface.batchnumvertices;i++)
9479                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9480 }
9481
9482 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9483 {
9484         int i;
9485         float f;
9486         const float *v;
9487         const float *c;
9488         float *c2;
9489         if (rsurface.passcolor4f)
9490         {
9491                 // generate color arrays
9492                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9493                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9494                 rsurface.passcolor4f_vertexbuffer = 0;
9495                 rsurface.passcolor4f_bufferoffset = 0;
9496                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4, c2 += 4)
9497                 {
9498                         f = RSurf_FogVertex(v);
9499                         c2[0] = c[0] * f;
9500                         c2[1] = c[1] * f;
9501                         c2[2] = c[2] * f;
9502                         c2[3] = c[3];
9503                 }
9504         }
9505         else
9506         {
9507                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9508                 rsurface.passcolor4f_vertexbuffer = 0;
9509                 rsurface.passcolor4f_bufferoffset = 0;
9510                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9511                 {
9512                         f = RSurf_FogVertex(v);
9513                         c2[0] = f;
9514                         c2[1] = f;
9515                         c2[2] = f;
9516                         c2[3] = 1;
9517                 }
9518         }
9519 }
9520
9521 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9522 {
9523         int i;
9524         float f;
9525         const float *v;
9526         const float *c;
9527         float *c2;
9528         if (!rsurface.passcolor4f)
9529                 return;
9530         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9531         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9532         rsurface.passcolor4f_vertexbuffer = 0;
9533         rsurface.passcolor4f_bufferoffset = 0;
9534         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)
9535         {
9536                 f = RSurf_FogVertex(v);
9537                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9538                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9539                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9540                 c2[3] = c[3];
9541         }
9542 }
9543
9544 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9545 {
9546         int i;
9547         const float *c;
9548         float *c2;
9549         if (!rsurface.passcolor4f)
9550                 return;
9551         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9552         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9553         rsurface.passcolor4f_vertexbuffer = 0;
9554         rsurface.passcolor4f_bufferoffset = 0;
9555         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9556         {
9557                 c2[0] = c[0] * r;
9558                 c2[1] = c[1] * g;
9559                 c2[2] = c[2] * b;
9560                 c2[3] = c[3] * a;
9561         }
9562 }
9563
9564 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9565 {
9566         int i;
9567         const float *c;
9568         float *c2;
9569         if (!rsurface.passcolor4f)
9570                 return;
9571         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9572         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9573         rsurface.passcolor4f_vertexbuffer = 0;
9574         rsurface.passcolor4f_bufferoffset = 0;
9575         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9576         {
9577                 c2[0] = c[0] + r_refdef.scene.ambient;
9578                 c2[1] = c[1] + r_refdef.scene.ambient;
9579                 c2[2] = c[2] + r_refdef.scene.ambient;
9580                 c2[3] = c[3];
9581         }
9582 }
9583
9584 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9585 {
9586         // TODO: optimize
9587         rsurface.passcolor4f = NULL;
9588         rsurface.passcolor4f_vertexbuffer = 0;
9589         rsurface.passcolor4f_bufferoffset = 0;
9590         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9591         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9592         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9593         GL_Color(r, g, b, a);
9594         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9595         RSurf_DrawBatch();
9596 }
9597
9598 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9599 {
9600         // TODO: optimize applyfog && applycolor case
9601         // just apply fog if necessary, and tint the fog color array if necessary
9602         rsurface.passcolor4f = NULL;
9603         rsurface.passcolor4f_vertexbuffer = 0;
9604         rsurface.passcolor4f_bufferoffset = 0;
9605         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9606         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9607         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9608         GL_Color(r, g, b, a);
9609         RSurf_DrawBatch();
9610 }
9611
9612 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9613 {
9614         // TODO: optimize
9615         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9616         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9617         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9618         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9619         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9620         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9621         GL_Color(r, g, b, a);
9622         RSurf_DrawBatch();
9623 }
9624
9625 static void RSurf_DrawBatch_GL11_ClampColor(void)
9626 {
9627         int i;
9628         const float *c1;
9629         float *c2;
9630         if (!rsurface.passcolor4f)
9631                 return;
9632         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9633         {
9634                 c2[0] = bound(0.0f, c1[0], 1.0f);
9635                 c2[1] = bound(0.0f, c1[1], 1.0f);
9636                 c2[2] = bound(0.0f, c1[2], 1.0f);
9637                 c2[3] = bound(0.0f, c1[3], 1.0f);
9638         }
9639 }
9640
9641 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9642 {
9643         int i;
9644         float f;
9645         const float *v;
9646         const float *n;
9647         float *c;
9648         //vec3_t eyedir;
9649
9650         // fake shading
9651         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9652         rsurface.passcolor4f_vertexbuffer = 0;
9653         rsurface.passcolor4f_bufferoffset = 0;
9654         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)
9655         {
9656                 f = -DotProduct(r_refdef.view.forward, n);
9657                 f = max(0, f);
9658                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9659                 f *= r_refdef.lightmapintensity;
9660                 Vector4Set(c, f, f, f, 1);
9661         }
9662 }
9663
9664 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9665 {
9666         RSurf_DrawBatch_GL11_ApplyFakeLight();
9667         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9668         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9669         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9670         GL_Color(r, g, b, a);
9671         RSurf_DrawBatch();
9672 }
9673
9674 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9675 {
9676         int i;
9677         float f;
9678         float alpha;
9679         const float *v;
9680         const float *n;
9681         float *c;
9682         vec3_t ambientcolor;
9683         vec3_t diffusecolor;
9684         vec3_t lightdir;
9685         // TODO: optimize
9686         // model lighting
9687         VectorCopy(rsurface.modellight_lightdir, lightdir);
9688         f = 0.5f * r_refdef.lightmapintensity;
9689         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9690         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9691         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9692         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9693         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9694         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9695         alpha = *a;
9696         if (VectorLength2(diffusecolor) > 0)
9697         {
9698                 // q3-style directional shading
9699                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9700                 rsurface.passcolor4f_vertexbuffer = 0;
9701                 rsurface.passcolor4f_bufferoffset = 0;
9702                 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)
9703                 {
9704                         if ((f = DotProduct(n, lightdir)) > 0)
9705                                 VectorMA(ambientcolor, f, diffusecolor, c);
9706                         else
9707                                 VectorCopy(ambientcolor, c);
9708                         c[3] = alpha;
9709                 }
9710                 *r = 1;
9711                 *g = 1;
9712                 *b = 1;
9713                 *a = 1;
9714                 *applycolor = false;
9715         }
9716         else
9717         {
9718                 *r = ambientcolor[0];
9719                 *g = ambientcolor[1];
9720                 *b = ambientcolor[2];
9721                 rsurface.passcolor4f = NULL;
9722                 rsurface.passcolor4f_vertexbuffer = 0;
9723                 rsurface.passcolor4f_bufferoffset = 0;
9724         }
9725 }
9726
9727 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9728 {
9729         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9730         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9731         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9732         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9733         GL_Color(r, g, b, a);
9734         RSurf_DrawBatch();
9735 }
9736
9737 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9738 {
9739         int i;
9740         float f;
9741         const float *v;
9742         float *c;
9743
9744         // fake shading
9745         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9746         rsurface.passcolor4f_vertexbuffer = 0;
9747         rsurface.passcolor4f_bufferoffset = 0;
9748
9749         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9750         {
9751                 f = 1 - RSurf_FogVertex(v);
9752                 c[0] = r;
9753                 c[1] = g;
9754                 c[2] = b;
9755                 c[3] = f * a;
9756         }
9757 }
9758
9759 void RSurf_SetupDepthAndCulling(void)
9760 {
9761         // submodels are biased to avoid z-fighting with world surfaces that they
9762         // may be exactly overlapping (avoids z-fighting artifacts on certain
9763         // doors and things in Quake maps)
9764         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9765         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9766         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9767         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9768 }
9769
9770 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9771 {
9772         // transparent sky would be ridiculous
9773         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9774                 return;
9775         R_SetupShader_Generic_NoTexture(false, false);
9776         skyrenderlater = true;
9777         RSurf_SetupDepthAndCulling();
9778         GL_DepthMask(true);
9779         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9780         // skymasking on them, and Quake3 never did sky masking (unlike
9781         // software Quake and software Quake2), so disable the sky masking
9782         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9783         // and skymasking also looks very bad when noclipping outside the
9784         // level, so don't use it then either.
9785         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9786         {
9787                 R_Mesh_ResetTextureState();
9788                 if (skyrendermasked)
9789                 {
9790                         R_SetupShader_DepthOrShadow(false, false);
9791                         // depth-only (masking)
9792                         GL_ColorMask(0,0,0,0);
9793                         // just to make sure that braindead drivers don't draw
9794                         // anything despite that colormask...
9795                         GL_BlendFunc(GL_ZERO, GL_ONE);
9796                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9797                         if (rsurface.batchvertex3fbuffer)
9798                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9799                         else
9800                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9801                 }
9802                 else
9803                 {
9804                         R_SetupShader_Generic_NoTexture(false, false);
9805                         // fog sky
9806                         GL_BlendFunc(GL_ONE, GL_ZERO);
9807                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9808                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9809                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9810                 }
9811                 RSurf_DrawBatch();
9812                 if (skyrendermasked)
9813                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9814         }
9815         R_Mesh_ResetTextureState();
9816         GL_Color(1, 1, 1, 1);
9817 }
9818
9819 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9820 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9821 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9822 {
9823         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9824                 return;
9825         if (prepass)
9826         {
9827                 // render screenspace normalmap to texture
9828                 GL_DepthMask(true);
9829                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9830                 RSurf_DrawBatch();
9831                 return;
9832         }
9833
9834         // bind lightmap texture
9835
9836         // water/refraction/reflection/camera surfaces have to be handled specially
9837         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9838         {
9839                 int start, end, startplaneindex;
9840                 for (start = 0;start < texturenumsurfaces;start = end)
9841                 {
9842                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9843                         if(startplaneindex < 0)
9844                         {
9845                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9846                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9847                                 end = start + 1;
9848                                 continue;
9849                         }
9850                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9851                                 ;
9852                         // now that we have a batch using the same planeindex, render it
9853                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9854                         {
9855                                 // render water or distortion background
9856                                 GL_DepthMask(true);
9857                                 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);
9858                                 RSurf_DrawBatch();
9859                                 // blend surface on top
9860                                 GL_DepthMask(false);
9861                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9862                                 RSurf_DrawBatch();
9863                         }
9864                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9865                         {
9866                                 // render surface with reflection texture as input
9867                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9868                                 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);
9869                                 RSurf_DrawBatch();
9870                         }
9871                 }
9872                 return;
9873         }
9874
9875         // render surface batch normally
9876         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9877         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);
9878         RSurf_DrawBatch();
9879 }
9880
9881 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9882 {
9883         // OpenGL 1.3 path - anything not completely ancient
9884         qboolean applycolor;
9885         qboolean applyfog;
9886         int layerindex;
9887         const texturelayer_t *layer;
9888         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);
9889         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9890
9891         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9892         {
9893                 vec4_t layercolor;
9894                 int layertexrgbscale;
9895                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9896                 {
9897                         if (layerindex == 0)
9898                                 GL_AlphaTest(true);
9899                         else
9900                         {
9901                                 GL_AlphaTest(false);
9902                                 GL_DepthFunc(GL_EQUAL);
9903                         }
9904                 }
9905                 GL_DepthMask(layer->depthmask && writedepth);
9906                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9907                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9908                 {
9909                         layertexrgbscale = 4;
9910                         VectorScale(layer->color, 0.25f, layercolor);
9911                 }
9912                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9913                 {
9914                         layertexrgbscale = 2;
9915                         VectorScale(layer->color, 0.5f, layercolor);
9916                 }
9917                 else
9918                 {
9919                         layertexrgbscale = 1;
9920                         VectorScale(layer->color, 1.0f, layercolor);
9921                 }
9922                 layercolor[3] = layer->color[3];
9923                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9924                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9925                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9926                 switch (layer->type)
9927                 {
9928                 case TEXTURELAYERTYPE_LITTEXTURE:
9929                         // single-pass lightmapped texture with 2x rgbscale
9930                         R_Mesh_TexBind(0, r_texture_white);
9931                         R_Mesh_TexMatrix(0, NULL);
9932                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9933                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9934                         R_Mesh_TexBind(1, layer->texture);
9935                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9936                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9937                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9938                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9939                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9940                         else if (FAKELIGHT_ENABLED)
9941                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9942                         else if (rsurface.uselightmaptexture)
9943                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9944                         else
9945                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9946                         break;
9947                 case TEXTURELAYERTYPE_TEXTURE:
9948                         // singletexture unlit texture with transparency support
9949                         R_Mesh_TexBind(0, layer->texture);
9950                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9951                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9952                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9953                         R_Mesh_TexBind(1, 0);
9954                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9955                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9956                         break;
9957                 case TEXTURELAYERTYPE_FOG:
9958                         // singletexture fogging
9959                         if (layer->texture)
9960                         {
9961                                 R_Mesh_TexBind(0, layer->texture);
9962                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9963                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9964                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9965                         }
9966                         else
9967                         {
9968                                 R_Mesh_TexBind(0, 0);
9969                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9970                         }
9971                         R_Mesh_TexBind(1, 0);
9972                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9973                         // generate a color array for the fog pass
9974                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9975                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9976                         RSurf_DrawBatch();
9977                         break;
9978                 default:
9979                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9980                 }
9981         }
9982         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9983         {
9984                 GL_DepthFunc(GL_LEQUAL);
9985                 GL_AlphaTest(false);
9986         }
9987 }
9988
9989 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9990 {
9991         // OpenGL 1.1 - crusty old voodoo path
9992         qboolean applyfog;
9993         int layerindex;
9994         const texturelayer_t *layer;
9995         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);
9996         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9997
9998         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9999         {
10000                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10001                 {
10002                         if (layerindex == 0)
10003                                 GL_AlphaTest(true);
10004                         else
10005                         {
10006                                 GL_AlphaTest(false);
10007                                 GL_DepthFunc(GL_EQUAL);
10008                         }
10009                 }
10010                 GL_DepthMask(layer->depthmask && writedepth);
10011                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
10012                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
10013                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
10014                 switch (layer->type)
10015                 {
10016                 case TEXTURELAYERTYPE_LITTEXTURE:
10017                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
10018                         {
10019                                 // two-pass lit texture with 2x rgbscale
10020                                 // first the lightmap pass
10021                                 R_Mesh_TexBind(0, r_texture_white);
10022                                 R_Mesh_TexMatrix(0, NULL);
10023                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10024                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
10025                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10026                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
10027                                 else if (FAKELIGHT_ENABLED)
10028                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
10029                                 else if (rsurface.uselightmaptexture)
10030                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
10031                                 else
10032                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
10033                                 // then apply the texture to it
10034                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
10035                                 R_Mesh_TexBind(0, layer->texture);
10036                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10037                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10038                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10039                                 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);
10040                         }
10041                         else
10042                         {
10043                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10044                                 R_Mesh_TexBind(0, layer->texture);
10045                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10046                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10047                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10048                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10049                                         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);
10050                                 else
10051                                         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);
10052                         }
10053                         break;
10054                 case TEXTURELAYERTYPE_TEXTURE:
10055                         // singletexture unlit texture with transparency support
10056                         R_Mesh_TexBind(0, layer->texture);
10057                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10058                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10059                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10060                         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);
10061                         break;
10062                 case TEXTURELAYERTYPE_FOG:
10063                         // singletexture fogging
10064                         if (layer->texture)
10065                         {
10066                                 R_Mesh_TexBind(0, layer->texture);
10067                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10068                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10069                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10070                         }
10071                         else
10072                         {
10073                                 R_Mesh_TexBind(0, 0);
10074                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10075                         }
10076                         // generate a color array for the fog pass
10077                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10078                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10079                         RSurf_DrawBatch();
10080                         break;
10081                 default:
10082                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10083                 }
10084         }
10085         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10086         {
10087                 GL_DepthFunc(GL_LEQUAL);
10088                 GL_AlphaTest(false);
10089         }
10090 }
10091
10092 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10093 {
10094         int vi;
10095         int j;
10096         r_vertexgeneric_t *batchvertex;
10097         float c[4];
10098
10099 //      R_Mesh_ResetTextureState();
10100         R_SetupShader_Generic_NoTexture(false, false);
10101
10102         if(rsurface.texture && rsurface.texture->currentskinframe)
10103         {
10104                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10105                 c[3] *= rsurface.texture->currentalpha;
10106         }
10107         else
10108         {
10109                 c[0] = 1;
10110                 c[1] = 0;
10111                 c[2] = 1;
10112                 c[3] = 1;
10113         }
10114
10115         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10116         {
10117                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10118                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10119                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10120         }
10121
10122         // brighten it up (as texture value 127 means "unlit")
10123         c[0] *= 2 * r_refdef.view.colorscale;
10124         c[1] *= 2 * r_refdef.view.colorscale;
10125         c[2] *= 2 * r_refdef.view.colorscale;
10126
10127         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10128                 c[3] *= r_wateralpha.value;
10129
10130         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10131         {
10132                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10133                 GL_DepthMask(false);
10134         }
10135         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10136         {
10137                 GL_BlendFunc(GL_ONE, GL_ONE);
10138                 GL_DepthMask(false);
10139         }
10140         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10141         {
10142                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10143                 GL_DepthMask(false);
10144         }
10145         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10146         {
10147                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10148                 GL_DepthMask(false);
10149         }
10150         else
10151         {
10152                 GL_BlendFunc(GL_ONE, GL_ZERO);
10153                 GL_DepthMask(writedepth);
10154         }
10155
10156         if (r_showsurfaces.integer == 3)
10157         {
10158                 rsurface.passcolor4f = NULL;
10159
10160                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10161                 {
10162                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10163
10164                         rsurface.passcolor4f = NULL;
10165                         rsurface.passcolor4f_vertexbuffer = 0;
10166                         rsurface.passcolor4f_bufferoffset = 0;
10167                 }
10168                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10169                 {
10170                         qboolean applycolor = true;
10171                         float one = 1.0;
10172
10173                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10174
10175                         r_refdef.lightmapintensity = 1;
10176                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10177                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10178                 }
10179                 else if (FAKELIGHT_ENABLED)
10180                 {
10181                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10182
10183                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10184                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10185                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10186                 }
10187                 else
10188                 {
10189                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10190
10191                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10192                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10193                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10194                 }
10195
10196                 if(!rsurface.passcolor4f)
10197                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10198
10199                 RSurf_DrawBatch_GL11_ApplyAmbient();
10200                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10201                 if(r_refdef.fogenabled)
10202                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10203                 RSurf_DrawBatch_GL11_ClampColor();
10204
10205                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10206                 R_SetupShader_Generic_NoTexture(false, false);
10207                 RSurf_DrawBatch();
10208         }
10209         else if (!r_refdef.view.showdebug)
10210         {
10211                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10212                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10213                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10214                 {
10215                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10216                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10217                 }
10218                 R_Mesh_PrepareVertices_Generic_Unlock();
10219                 RSurf_DrawBatch();
10220         }
10221         else if (r_showsurfaces.integer == 4)
10222         {
10223                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10224                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10225                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10226                 {
10227                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10228                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10229                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10230                 }
10231                 R_Mesh_PrepareVertices_Generic_Unlock();
10232                 RSurf_DrawBatch();
10233         }
10234         else if (r_showsurfaces.integer == 2)
10235         {
10236                 const int *e;
10237                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10238                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10239                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10240                 {
10241                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10242                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10243                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10244                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10245                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10246                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10247                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10248                 }
10249                 R_Mesh_PrepareVertices_Generic_Unlock();
10250                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10251         }
10252         else
10253         {
10254                 int texturesurfaceindex;
10255                 int k;
10256                 const msurface_t *surface;
10257                 float surfacecolor4f[4];
10258                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10259                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10260                 vi = 0;
10261                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10262                 {
10263                         surface = texturesurfacelist[texturesurfaceindex];
10264                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10265                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10266                         for (j = 0;j < surface->num_vertices;j++)
10267                         {
10268                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10269                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10270                                 vi++;
10271                         }
10272                 }
10273                 R_Mesh_PrepareVertices_Generic_Unlock();
10274                 RSurf_DrawBatch();
10275         }
10276 }
10277
10278 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10279 {
10280         CHECKGLERROR
10281         RSurf_SetupDepthAndCulling();
10282         if (r_showsurfaces.integer)
10283         {
10284                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10285                 return;
10286         }
10287         switch (vid.renderpath)
10288         {
10289         case RENDERPATH_GL20:
10290         case RENDERPATH_D3D9:
10291         case RENDERPATH_D3D10:
10292         case RENDERPATH_D3D11:
10293         case RENDERPATH_SOFT:
10294         case RENDERPATH_GLES2:
10295                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10296                 break;
10297         case RENDERPATH_GL13:
10298         case RENDERPATH_GLES1:
10299                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10300                 break;
10301         case RENDERPATH_GL11:
10302                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10303                 break;
10304         }
10305         CHECKGLERROR
10306 }
10307
10308 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10309 {
10310         CHECKGLERROR
10311         RSurf_SetupDepthAndCulling();
10312         if (r_showsurfaces.integer)
10313         {
10314                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10315                 return;
10316         }
10317         switch (vid.renderpath)
10318         {
10319         case RENDERPATH_GL20:
10320         case RENDERPATH_D3D9:
10321         case RENDERPATH_D3D10:
10322         case RENDERPATH_D3D11:
10323         case RENDERPATH_SOFT:
10324         case RENDERPATH_GLES2:
10325                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10326                 break;
10327         case RENDERPATH_GL13:
10328         case RENDERPATH_GLES1:
10329                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10330                 break;
10331         case RENDERPATH_GL11:
10332                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10333                 break;
10334         }
10335         CHECKGLERROR
10336 }
10337
10338 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10339 {
10340         int i, j;
10341         int texturenumsurfaces, endsurface;
10342         texture_t *texture;
10343         const msurface_t *surface;
10344         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10345
10346         // if the model is static it doesn't matter what value we give for
10347         // wantnormals and wanttangents, so this logic uses only rules applicable
10348         // to a model, knowing that they are meaningless otherwise
10349         if (ent == r_refdef.scene.worldentity)
10350                 RSurf_ActiveWorldEntity();
10351         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10352                 RSurf_ActiveModelEntity(ent, false, false, false);
10353         else
10354         {
10355                 switch (vid.renderpath)
10356                 {
10357                 case RENDERPATH_GL20:
10358                 case RENDERPATH_D3D9:
10359                 case RENDERPATH_D3D10:
10360                 case RENDERPATH_D3D11:
10361                 case RENDERPATH_SOFT:
10362                 case RENDERPATH_GLES2:
10363                         RSurf_ActiveModelEntity(ent, true, true, false);
10364                         break;
10365                 case RENDERPATH_GL11:
10366                 case RENDERPATH_GL13:
10367                 case RENDERPATH_GLES1:
10368                         RSurf_ActiveModelEntity(ent, true, false, false);
10369                         break;
10370                 }
10371         }
10372
10373         if (r_transparentdepthmasking.integer)
10374         {
10375                 qboolean setup = false;
10376                 for (i = 0;i < numsurfaces;i = j)
10377                 {
10378                         j = i + 1;
10379                         surface = rsurface.modelsurfaces + surfacelist[i];
10380                         texture = surface->texture;
10381                         rsurface.texture = R_GetCurrentTexture(texture);
10382                         rsurface.lightmaptexture = NULL;
10383                         rsurface.deluxemaptexture = NULL;
10384                         rsurface.uselightmaptexture = false;
10385                         // scan ahead until we find a different texture
10386                         endsurface = min(i + 1024, numsurfaces);
10387                         texturenumsurfaces = 0;
10388                         texturesurfacelist[texturenumsurfaces++] = surface;
10389                         for (;j < endsurface;j++)
10390                         {
10391                                 surface = rsurface.modelsurfaces + surfacelist[j];
10392                                 if (texture != surface->texture)
10393                                         break;
10394                                 texturesurfacelist[texturenumsurfaces++] = surface;
10395                         }
10396                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10397                                 continue;
10398                         // render the range of surfaces as depth
10399                         if (!setup)
10400                         {
10401                                 setup = true;
10402                                 GL_ColorMask(0,0,0,0);
10403                                 GL_Color(1,1,1,1);
10404                                 GL_DepthTest(true);
10405                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10406                                 GL_DepthMask(true);
10407 //                              R_Mesh_ResetTextureState();
10408                                 R_SetupShader_DepthOrShadow(false, false);
10409                         }
10410                         RSurf_SetupDepthAndCulling();
10411                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10412                         if (rsurface.batchvertex3fbuffer)
10413                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10414                         else
10415                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10416                         RSurf_DrawBatch();
10417                 }
10418                 if (setup)
10419                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10420         }
10421
10422         for (i = 0;i < numsurfaces;i = j)
10423         {
10424                 j = i + 1;
10425                 surface = rsurface.modelsurfaces + surfacelist[i];
10426                 texture = surface->texture;
10427                 rsurface.texture = R_GetCurrentTexture(texture);
10428                 // scan ahead until we find a different texture
10429                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10430                 texturenumsurfaces = 0;
10431                 texturesurfacelist[texturenumsurfaces++] = surface;
10432                 if(FAKELIGHT_ENABLED)
10433                 {
10434                         rsurface.lightmaptexture = NULL;
10435                         rsurface.deluxemaptexture = NULL;
10436                         rsurface.uselightmaptexture = false;
10437                         for (;j < endsurface;j++)
10438                         {
10439                                 surface = rsurface.modelsurfaces + surfacelist[j];
10440                                 if (texture != surface->texture)
10441                                         break;
10442                                 texturesurfacelist[texturenumsurfaces++] = surface;
10443                         }
10444                 }
10445                 else
10446                 {
10447                         rsurface.lightmaptexture = surface->lightmaptexture;
10448                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10449                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10450                         for (;j < endsurface;j++)
10451                         {
10452                                 surface = rsurface.modelsurfaces + surfacelist[j];
10453                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10454                                         break;
10455                                 texturesurfacelist[texturenumsurfaces++] = surface;
10456                         }
10457                 }
10458                 // render the range of surfaces
10459                 if (ent == r_refdef.scene.worldentity)
10460                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10461                 else
10462                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10463         }
10464         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10465 }
10466
10467 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10468 {
10469         // transparent surfaces get pushed off into the transparent queue
10470         int surfacelistindex;
10471         const msurface_t *surface;
10472         vec3_t tempcenter, center;
10473         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10474         {
10475                 surface = texturesurfacelist[surfacelistindex];
10476                 if (r_transparent_sortsurfacesbynearest.integer)
10477                 {
10478                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10479                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10480                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10481                 }
10482                 else
10483                 {
10484                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10485                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10486                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10487                 }
10488                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10489                 if (rsurface.entity->transparent_offset) // transparent offset
10490                 {
10491                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10492                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10493                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10494                 }
10495                 R_MeshQueue_AddTransparent((rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : ((rsurface.entity->flags & RENDER_WORLDOBJECT) ? MESHQUEUE_SORT_SKY : MESHQUEUE_SORT_DISTANCE), center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10496         }
10497 }
10498
10499 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10500 {
10501         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10502                 return;
10503         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10504                 return;
10505         RSurf_SetupDepthAndCulling();
10506         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10507         if (rsurface.batchvertex3fbuffer)
10508                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10509         else
10510                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10511         RSurf_DrawBatch();
10512 }
10513
10514 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10515 {
10516         CHECKGLERROR
10517         if (depthonly)
10518                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10519         else if (prepass)
10520         {
10521                 if (!rsurface.texture->currentnumlayers)
10522                         return;
10523                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10524                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10525                 else
10526                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10527         }
10528         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10529                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10530         else if (!rsurface.texture->currentnumlayers)
10531                 return;
10532         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10533         {
10534                 // in the deferred case, transparent surfaces were queued during prepass
10535                 if (!r_shadow_usingdeferredprepass)
10536                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10537         }
10538         else
10539         {
10540                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10541                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10542         }
10543         CHECKGLERROR
10544 }
10545
10546 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10547 {
10548         int i, j;
10549         texture_t *texture;
10550         R_FrameData_SetMark();
10551         // break the surface list down into batches by texture and use of lightmapping
10552         for (i = 0;i < numsurfaces;i = j)
10553         {
10554                 j = i + 1;
10555                 // texture is the base texture pointer, rsurface.texture is the
10556                 // current frame/skin the texture is directing us to use (for example
10557                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10558                 // use skin 1 instead)
10559                 texture = surfacelist[i]->texture;
10560                 rsurface.texture = R_GetCurrentTexture(texture);
10561                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10562                 {
10563                         // if this texture is not the kind we want, skip ahead to the next one
10564                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10565                                 ;
10566                         continue;
10567                 }
10568                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10569                 {
10570                         rsurface.lightmaptexture = NULL;
10571                         rsurface.deluxemaptexture = NULL;
10572                         rsurface.uselightmaptexture = false;
10573                         // simply scan ahead until we find a different texture or lightmap state
10574                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10575                                 ;
10576                 }
10577                 else
10578                 {
10579                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10580                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10581                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10582                         // simply scan ahead until we find a different texture or lightmap state
10583                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10584                                 ;
10585                 }
10586                 // render the range of surfaces
10587                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10588         }
10589         R_FrameData_ReturnToMark();
10590 }
10591
10592 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10593 {
10594         CHECKGLERROR
10595         if (depthonly)
10596                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10597         else if (prepass)
10598         {
10599                 if (!rsurface.texture->currentnumlayers)
10600                         return;
10601                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10602                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10603                 else
10604                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10605         }
10606         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10607                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10608         else if (!rsurface.texture->currentnumlayers)
10609                 return;
10610         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10611         {
10612                 // in the deferred case, transparent surfaces were queued during prepass
10613                 if (!r_shadow_usingdeferredprepass)
10614                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10615         }
10616         else
10617         {
10618                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10619                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10620         }
10621         CHECKGLERROR
10622 }
10623
10624 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10625 {
10626         int i, j;
10627         texture_t *texture;
10628         R_FrameData_SetMark();
10629         // break the surface list down into batches by texture and use of lightmapping
10630         for (i = 0;i < numsurfaces;i = j)
10631         {
10632                 j = i + 1;
10633                 // texture is the base texture pointer, rsurface.texture is the
10634                 // current frame/skin the texture is directing us to use (for example
10635                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10636                 // use skin 1 instead)
10637                 texture = surfacelist[i]->texture;
10638                 rsurface.texture = R_GetCurrentTexture(texture);
10639                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10640                 {
10641                         // if this texture is not the kind we want, skip ahead to the next one
10642                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10643                                 ;
10644                         continue;
10645                 }
10646                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10647                 {
10648                         rsurface.lightmaptexture = NULL;
10649                         rsurface.deluxemaptexture = NULL;
10650                         rsurface.uselightmaptexture = false;
10651                         // simply scan ahead until we find a different texture or lightmap state
10652                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10653                                 ;
10654                 }
10655                 else
10656                 {
10657                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10658                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10659                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10660                         // simply scan ahead until we find a different texture or lightmap state
10661                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10662                                 ;
10663                 }
10664                 // render the range of surfaces
10665                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10666         }
10667         R_FrameData_ReturnToMark();
10668 }
10669
10670 float locboxvertex3f[6*4*3] =
10671 {
10672         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10673         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10674         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10675         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10676         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10677         1,0,0, 0,0,0, 0,1,0, 1,1,0
10678 };
10679
10680 unsigned short locboxelements[6*2*3] =
10681 {
10682          0, 1, 2, 0, 2, 3,
10683          4, 5, 6, 4, 6, 7,
10684          8, 9,10, 8,10,11,
10685         12,13,14, 12,14,15,
10686         16,17,18, 16,18,19,
10687         20,21,22, 20,22,23
10688 };
10689
10690 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10691 {
10692         int i, j;
10693         cl_locnode_t *loc = (cl_locnode_t *)ent;
10694         vec3_t mins, size;
10695         float vertex3f[6*4*3];
10696         CHECKGLERROR
10697         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10698         GL_DepthMask(false);
10699         GL_DepthRange(0, 1);
10700         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10701         GL_DepthTest(true);
10702         GL_CullFace(GL_NONE);
10703         R_EntityMatrix(&identitymatrix);
10704
10705 //      R_Mesh_ResetTextureState();
10706
10707         i = surfacelist[0];
10708         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10709                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10710                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10711                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10712
10713         if (VectorCompare(loc->mins, loc->maxs))
10714         {
10715                 VectorSet(size, 2, 2, 2);
10716                 VectorMA(loc->mins, -0.5f, size, mins);
10717         }
10718         else
10719         {
10720                 VectorCopy(loc->mins, mins);
10721                 VectorSubtract(loc->maxs, loc->mins, size);
10722         }
10723
10724         for (i = 0;i < 6*4*3;)
10725                 for (j = 0;j < 3;j++, i++)
10726                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10727
10728         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10729         R_SetupShader_Generic_NoTexture(false, false);
10730         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10731 }
10732
10733 void R_DrawLocs(void)
10734 {
10735         int index;
10736         cl_locnode_t *loc, *nearestloc;
10737         vec3_t center;
10738         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10739         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10740         {
10741                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10742                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10743         }
10744 }
10745
10746 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10747 {
10748         if (decalsystem->decals)
10749                 Mem_Free(decalsystem->decals);
10750         memset(decalsystem, 0, sizeof(*decalsystem));
10751 }
10752
10753 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)
10754 {
10755         tridecal_t *decal;
10756         tridecal_t *decals;
10757         int i;
10758
10759         // expand or initialize the system
10760         if (decalsystem->maxdecals <= decalsystem->numdecals)
10761         {
10762                 decalsystem_t old = *decalsystem;
10763                 qboolean useshortelements;
10764                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10765                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10766                 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)));
10767                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10768                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10769                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10770                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10771                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10772                 if (decalsystem->numdecals)
10773                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10774                 if (old.decals)
10775                         Mem_Free(old.decals);
10776                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10777                         decalsystem->element3i[i] = i;
10778                 if (useshortelements)
10779                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10780                                 decalsystem->element3s[i] = i;
10781         }
10782
10783         // grab a decal and search for another free slot for the next one
10784         decals = decalsystem->decals;
10785         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10786         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10787                 ;
10788         decalsystem->freedecal = i;
10789         if (decalsystem->numdecals <= i)
10790                 decalsystem->numdecals = i + 1;
10791
10792         // initialize the decal
10793         decal->lived = 0;
10794         decal->triangleindex = triangleindex;
10795         decal->surfaceindex = surfaceindex;
10796         decal->decalsequence = decalsequence;
10797         decal->color4f[0][0] = c0[0];
10798         decal->color4f[0][1] = c0[1];
10799         decal->color4f[0][2] = c0[2];
10800         decal->color4f[0][3] = 1;
10801         decal->color4f[1][0] = c1[0];
10802         decal->color4f[1][1] = c1[1];
10803         decal->color4f[1][2] = c1[2];
10804         decal->color4f[1][3] = 1;
10805         decal->color4f[2][0] = c2[0];
10806         decal->color4f[2][1] = c2[1];
10807         decal->color4f[2][2] = c2[2];
10808         decal->color4f[2][3] = 1;
10809         decal->vertex3f[0][0] = v0[0];
10810         decal->vertex3f[0][1] = v0[1];
10811         decal->vertex3f[0][2] = v0[2];
10812         decal->vertex3f[1][0] = v1[0];
10813         decal->vertex3f[1][1] = v1[1];
10814         decal->vertex3f[1][2] = v1[2];
10815         decal->vertex3f[2][0] = v2[0];
10816         decal->vertex3f[2][1] = v2[1];
10817         decal->vertex3f[2][2] = v2[2];
10818         decal->texcoord2f[0][0] = t0[0];
10819         decal->texcoord2f[0][1] = t0[1];
10820         decal->texcoord2f[1][0] = t1[0];
10821         decal->texcoord2f[1][1] = t1[1];
10822         decal->texcoord2f[2][0] = t2[0];
10823         decal->texcoord2f[2][1] = t2[1];
10824         TriangleNormal(v0, v1, v2, decal->plane);
10825         VectorNormalize(decal->plane);
10826         decal->plane[3] = DotProduct(v0, decal->plane);
10827 }
10828
10829 extern cvar_t cl_decals_bias;
10830 extern cvar_t cl_decals_models;
10831 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10832 // baseparms, parms, temps
10833 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)
10834 {
10835         int cornerindex;
10836         int index;
10837         float v[9][3];
10838         const float *vertex3f;
10839         const float *normal3f;
10840         int numpoints;
10841         float points[2][9][3];
10842         float temp[3];
10843         float tc[9][2];
10844         float f;
10845         float c[9][4];
10846         const int *e;
10847
10848         e = rsurface.modelelement3i + 3*triangleindex;
10849
10850         vertex3f = rsurface.modelvertex3f;
10851         normal3f = rsurface.modelnormal3f;
10852
10853         if (normal3f)
10854         {
10855                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10856                 {
10857                         index = 3*e[cornerindex];
10858                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10859                 }
10860         }
10861         else
10862         {
10863                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10864                 {
10865                         index = 3*e[cornerindex];
10866                         VectorCopy(vertex3f + index, v[cornerindex]);
10867                 }
10868         }
10869
10870         // cull backfaces
10871         //TriangleNormal(v[0], v[1], v[2], normal);
10872         //if (DotProduct(normal, localnormal) < 0.0f)
10873         //      continue;
10874         // clip by each of the box planes formed from the projection matrix
10875         // if anything survives, we emit the decal
10876         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]);
10877         if (numpoints < 3)
10878                 return;
10879         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]);
10880         if (numpoints < 3)
10881                 return;
10882         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]);
10883         if (numpoints < 3)
10884                 return;
10885         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]);
10886         if (numpoints < 3)
10887                 return;
10888         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]);
10889         if (numpoints < 3)
10890                 return;
10891         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]);
10892         if (numpoints < 3)
10893                 return;
10894         // some part of the triangle survived, so we have to accept it...
10895         if (dynamic)
10896         {
10897                 // dynamic always uses the original triangle
10898                 numpoints = 3;
10899                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10900                 {
10901                         index = 3*e[cornerindex];
10902                         VectorCopy(vertex3f + index, v[cornerindex]);
10903                 }
10904         }
10905         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10906         {
10907                 // convert vertex positions to texcoords
10908                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10909                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10910                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10911                 // calculate distance fade from the projection origin
10912                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10913                 f = bound(0.0f, f, 1.0f);
10914                 c[cornerindex][0] = r * f;
10915                 c[cornerindex][1] = g * f;
10916                 c[cornerindex][2] = b * f;
10917                 c[cornerindex][3] = 1.0f;
10918                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10919         }
10920         if (dynamic)
10921                 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);
10922         else
10923                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10924                         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);
10925 }
10926 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)
10927 {
10928         matrix4x4_t projection;
10929         decalsystem_t *decalsystem;
10930         qboolean dynamic;
10931         dp_model_t *model;
10932         const msurface_t *surface;
10933         const msurface_t *surfaces;
10934         const int *surfacelist;
10935         const texture_t *texture;
10936         int numtriangles;
10937         int numsurfacelist;
10938         int surfacelistindex;
10939         int surfaceindex;
10940         int triangleindex;
10941         float localorigin[3];
10942         float localnormal[3];
10943         float localmins[3];
10944         float localmaxs[3];
10945         float localsize;
10946         //float normal[3];
10947         float planes[6][4];
10948         float angles[3];
10949         bih_t *bih;
10950         int bih_triangles_count;
10951         int bih_triangles[256];
10952         int bih_surfaces[256];
10953
10954         decalsystem = &ent->decalsystem;
10955         model = ent->model;
10956         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10957         {
10958                 R_DecalSystem_Reset(&ent->decalsystem);
10959                 return;
10960         }
10961
10962         if (!model->brush.data_leafs && !cl_decals_models.integer)
10963         {
10964                 if (decalsystem->model)
10965                         R_DecalSystem_Reset(decalsystem);
10966                 return;
10967         }
10968
10969         if (decalsystem->model != model)
10970                 R_DecalSystem_Reset(decalsystem);
10971         decalsystem->model = model;
10972
10973         RSurf_ActiveModelEntity(ent, true, false, false);
10974
10975         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10976         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10977         VectorNormalize(localnormal);
10978         localsize = worldsize*rsurface.inversematrixscale;
10979         localmins[0] = localorigin[0] - localsize;
10980         localmins[1] = localorigin[1] - localsize;
10981         localmins[2] = localorigin[2] - localsize;
10982         localmaxs[0] = localorigin[0] + localsize;
10983         localmaxs[1] = localorigin[1] + localsize;
10984         localmaxs[2] = localorigin[2] + localsize;
10985
10986         //VectorCopy(localnormal, planes[4]);
10987         //VectorVectors(planes[4], planes[2], planes[0]);
10988         AnglesFromVectors(angles, localnormal, NULL, false);
10989         AngleVectors(angles, planes[0], planes[2], planes[4]);
10990         VectorNegate(planes[0], planes[1]);
10991         VectorNegate(planes[2], planes[3]);
10992         VectorNegate(planes[4], planes[5]);
10993         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10994         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10995         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10996         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10997         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10998         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10999
11000 #if 1
11001 // works
11002 {
11003         matrix4x4_t forwardprojection;
11004         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
11005         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
11006 }
11007 #else
11008 // broken
11009 {
11010         float projectionvector[4][3];
11011         VectorScale(planes[0], ilocalsize, projectionvector[0]);
11012         VectorScale(planes[2], ilocalsize, projectionvector[1]);
11013         VectorScale(planes[4], ilocalsize, projectionvector[2]);
11014         projectionvector[0][0] = planes[0][0] * ilocalsize;
11015         projectionvector[0][1] = planes[1][0] * ilocalsize;
11016         projectionvector[0][2] = planes[2][0] * ilocalsize;
11017         projectionvector[1][0] = planes[0][1] * ilocalsize;
11018         projectionvector[1][1] = planes[1][1] * ilocalsize;
11019         projectionvector[1][2] = planes[2][1] * ilocalsize;
11020         projectionvector[2][0] = planes[0][2] * ilocalsize;
11021         projectionvector[2][1] = planes[1][2] * ilocalsize;
11022         projectionvector[2][2] = planes[2][2] * ilocalsize;
11023         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
11024         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
11025         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
11026         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
11027 }
11028 #endif
11029
11030         dynamic = model->surfmesh.isanimated;
11031         numsurfacelist = model->nummodelsurfaces;
11032         surfacelist = model->sortedmodelsurfaces;
11033         surfaces = model->data_surfaces;
11034
11035         bih = NULL;
11036         bih_triangles_count = -1;
11037         if(!dynamic)
11038         {
11039                 if(model->render_bih.numleafs)
11040                         bih = &model->render_bih;
11041                 else if(model->collision_bih.numleafs)
11042                         bih = &model->collision_bih;
11043         }
11044         if(bih)
11045                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11046         if(bih_triangles_count == 0)
11047                 return;
11048         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11049                 return;
11050         if(bih_triangles_count > 0)
11051         {
11052                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11053                 {
11054                         surfaceindex = bih_surfaces[triangleindex];
11055                         surface = surfaces + surfaceindex;
11056                         texture = surface->texture;
11057                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11058                                 continue;
11059                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11060                                 continue;
11061                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11062                 }
11063         }
11064         else
11065         {
11066                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11067                 {
11068                         surfaceindex = surfacelist[surfacelistindex];
11069                         surface = surfaces + surfaceindex;
11070                         // check cull box first because it rejects more than any other check
11071                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11072                                 continue;
11073                         // skip transparent surfaces
11074                         texture = surface->texture;
11075                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11076                                 continue;
11077                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11078                                 continue;
11079                         numtriangles = surface->num_triangles;
11080                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11081                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11082                 }
11083         }
11084 }
11085
11086 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11087 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)
11088 {
11089         int renderentityindex;
11090         float worldmins[3];
11091         float worldmaxs[3];
11092         entity_render_t *ent;
11093
11094         if (!cl_decals_newsystem.integer)
11095                 return;
11096
11097         worldmins[0] = worldorigin[0] - worldsize;
11098         worldmins[1] = worldorigin[1] - worldsize;
11099         worldmins[2] = worldorigin[2] - worldsize;
11100         worldmaxs[0] = worldorigin[0] + worldsize;
11101         worldmaxs[1] = worldorigin[1] + worldsize;
11102         worldmaxs[2] = worldorigin[2] + worldsize;
11103
11104         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11105
11106         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11107         {
11108                 ent = r_refdef.scene.entities[renderentityindex];
11109                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11110                         continue;
11111
11112                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11113         }
11114 }
11115
11116 typedef struct r_decalsystem_splatqueue_s
11117 {
11118         vec3_t worldorigin;
11119         vec3_t worldnormal;
11120         float color[4];
11121         float tcrange[4];
11122         float worldsize;
11123         int decalsequence;
11124 }
11125 r_decalsystem_splatqueue_t;
11126
11127 int r_decalsystem_numqueued = 0;
11128 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11129
11130 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)
11131 {
11132         r_decalsystem_splatqueue_t *queue;
11133
11134         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11135                 return;
11136
11137         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11138         VectorCopy(worldorigin, queue->worldorigin);
11139         VectorCopy(worldnormal, queue->worldnormal);
11140         Vector4Set(queue->color, r, g, b, a);
11141         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11142         queue->worldsize = worldsize;
11143         queue->decalsequence = cl.decalsequence++;
11144 }
11145
11146 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11147 {
11148         int i;
11149         r_decalsystem_splatqueue_t *queue;
11150
11151         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11152                 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);
11153         r_decalsystem_numqueued = 0;
11154 }
11155
11156 extern cvar_t cl_decals_max;
11157 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11158 {
11159         int i;
11160         decalsystem_t *decalsystem = &ent->decalsystem;
11161         int numdecals;
11162         int killsequence;
11163         tridecal_t *decal;
11164         float frametime;
11165         float lifetime;
11166
11167         if (!decalsystem->numdecals)
11168                 return;
11169
11170         if (r_showsurfaces.integer)
11171                 return;
11172
11173         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11174         {
11175                 R_DecalSystem_Reset(decalsystem);
11176                 return;
11177         }
11178
11179         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11180         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11181
11182         if (decalsystem->lastupdatetime)
11183                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11184         else
11185                 frametime = 0;
11186         decalsystem->lastupdatetime = r_refdef.scene.time;
11187         decal = decalsystem->decals;
11188         numdecals = decalsystem->numdecals;
11189
11190         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11191         {
11192                 if (decal->color4f[0][3])
11193                 {
11194                         decal->lived += frametime;
11195                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11196                         {
11197                                 memset(decal, 0, sizeof(*decal));
11198                                 if (decalsystem->freedecal > i)
11199                                         decalsystem->freedecal = i;
11200                         }
11201                 }
11202         }
11203         decal = decalsystem->decals;
11204         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11205                 numdecals--;
11206
11207         // collapse the array by shuffling the tail decals into the gaps
11208         for (;;)
11209         {
11210                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11211                         decalsystem->freedecal++;
11212                 if (decalsystem->freedecal == numdecals)
11213                         break;
11214                 decal[decalsystem->freedecal] = decal[--numdecals];
11215         }
11216
11217         decalsystem->numdecals = numdecals;
11218
11219         if (numdecals <= 0)
11220         {
11221                 // if there are no decals left, reset decalsystem
11222                 R_DecalSystem_Reset(decalsystem);
11223         }
11224 }
11225
11226 extern skinframe_t *decalskinframe;
11227 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11228 {
11229         int i;
11230         decalsystem_t *decalsystem = &ent->decalsystem;
11231         int numdecals;
11232         tridecal_t *decal;
11233         float faderate;
11234         float alpha;
11235         float *v3f;
11236         float *c4f;
11237         float *t2f;
11238         const int *e;
11239         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11240         int numtris = 0;
11241
11242         numdecals = decalsystem->numdecals;
11243         if (!numdecals)
11244                 return;
11245
11246         if (r_showsurfaces.integer)
11247                 return;
11248
11249         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11250         {
11251                 R_DecalSystem_Reset(decalsystem);
11252                 return;
11253         }
11254
11255         // if the model is static it doesn't matter what value we give for
11256         // wantnormals and wanttangents, so this logic uses only rules applicable
11257         // to a model, knowing that they are meaningless otherwise
11258         if (ent == r_refdef.scene.worldentity)
11259                 RSurf_ActiveWorldEntity();
11260         else
11261                 RSurf_ActiveModelEntity(ent, false, false, false);
11262
11263         decalsystem->lastupdatetime = r_refdef.scene.time;
11264         decal = decalsystem->decals;
11265
11266         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11267
11268         // update vertex positions for animated models
11269         v3f = decalsystem->vertex3f;
11270         c4f = decalsystem->color4f;
11271         t2f = decalsystem->texcoord2f;
11272         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11273         {
11274                 if (!decal->color4f[0][3])
11275                         continue;
11276
11277                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11278                         continue;
11279
11280                 // skip backfaces
11281                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11282                         continue;
11283
11284                 // update color values for fading decals
11285                 if (decal->lived >= cl_decals_time.value)
11286                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11287                 else
11288                         alpha = 1.0f;
11289
11290                 c4f[ 0] = decal->color4f[0][0] * alpha;
11291                 c4f[ 1] = decal->color4f[0][1] * alpha;
11292                 c4f[ 2] = decal->color4f[0][2] * alpha;
11293                 c4f[ 3] = 1;
11294                 c4f[ 4] = decal->color4f[1][0] * alpha;
11295                 c4f[ 5] = decal->color4f[1][1] * alpha;
11296                 c4f[ 6] = decal->color4f[1][2] * alpha;
11297                 c4f[ 7] = 1;
11298                 c4f[ 8] = decal->color4f[2][0] * alpha;
11299                 c4f[ 9] = decal->color4f[2][1] * alpha;
11300                 c4f[10] = decal->color4f[2][2] * alpha;
11301                 c4f[11] = 1;
11302
11303                 t2f[0] = decal->texcoord2f[0][0];
11304                 t2f[1] = decal->texcoord2f[0][1];
11305                 t2f[2] = decal->texcoord2f[1][0];
11306                 t2f[3] = decal->texcoord2f[1][1];
11307                 t2f[4] = decal->texcoord2f[2][0];
11308                 t2f[5] = decal->texcoord2f[2][1];
11309
11310                 // update vertex positions for animated models
11311                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11312                 {
11313                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11314                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11315                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11316                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11317                 }
11318                 else
11319                 {
11320                         VectorCopy(decal->vertex3f[0], v3f);
11321                         VectorCopy(decal->vertex3f[1], v3f + 3);
11322                         VectorCopy(decal->vertex3f[2], v3f + 6);
11323                 }
11324
11325                 if (r_refdef.fogenabled)
11326                 {
11327                         alpha = RSurf_FogVertex(v3f);
11328                         VectorScale(c4f, alpha, c4f);
11329                         alpha = RSurf_FogVertex(v3f + 3);
11330                         VectorScale(c4f + 4, alpha, c4f + 4);
11331                         alpha = RSurf_FogVertex(v3f + 6);
11332                         VectorScale(c4f + 8, alpha, c4f + 8);
11333                 }
11334
11335                 v3f += 9;
11336                 c4f += 12;
11337                 t2f += 6;
11338                 numtris++;
11339         }
11340
11341         if (numtris > 0)
11342         {
11343                 r_refdef.stats.drawndecals += numtris;
11344
11345                 // now render the decals all at once
11346                 // (this assumes they all use one particle font texture!)
11347                 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);
11348 //              R_Mesh_ResetTextureState();
11349                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11350                 GL_DepthMask(false);
11351                 GL_DepthRange(0, 1);
11352                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11353                 GL_DepthTest(true);
11354                 GL_CullFace(GL_NONE);
11355                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11356                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11357                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11358         }
11359 }
11360
11361 static void R_DrawModelDecals(void)
11362 {
11363         int i, numdecals;
11364
11365         // fade faster when there are too many decals
11366         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11367         for (i = 0;i < r_refdef.scene.numentities;i++)
11368                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11369
11370         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11371         for (i = 0;i < r_refdef.scene.numentities;i++)
11372                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11373                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11374
11375         R_DecalSystem_ApplySplatEntitiesQueue();
11376
11377         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11378         for (i = 0;i < r_refdef.scene.numentities;i++)
11379                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11380
11381         r_refdef.stats.totaldecals += numdecals;
11382
11383         if (r_showsurfaces.integer)
11384                 return;
11385
11386         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11387
11388         for (i = 0;i < r_refdef.scene.numentities;i++)
11389         {
11390                 if (!r_refdef.viewcache.entityvisible[i])
11391                         continue;
11392                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11393                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11394         }
11395 }
11396
11397 extern cvar_t mod_collision_bih;
11398 static void R_DrawDebugModel(void)
11399 {
11400         entity_render_t *ent = rsurface.entity;
11401         int i, j, k, l, flagsmask;
11402         const msurface_t *surface;
11403         dp_model_t *model = ent->model;
11404         vec3_t v;
11405
11406         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11407                 return;
11408
11409         if (r_showoverdraw.value > 0)
11410         {
11411                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11412                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11413                 R_SetupShader_Generic_NoTexture(false, false);
11414                 GL_DepthTest(false);
11415                 GL_DepthMask(false);
11416                 GL_DepthRange(0, 1);
11417                 GL_BlendFunc(GL_ONE, GL_ONE);
11418                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11419                 {
11420                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11421                                 continue;
11422                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11423                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11424                         {
11425                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11426                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11427                                 if (!rsurface.texture->currentlayers->depthmask)
11428                                         GL_Color(c, 0, 0, 1.0f);
11429                                 else if (ent == r_refdef.scene.worldentity)
11430                                         GL_Color(c, c, c, 1.0f);
11431                                 else
11432                                         GL_Color(0, c, 0, 1.0f);
11433                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11434                                 RSurf_DrawBatch();
11435                         }
11436                 }
11437                 rsurface.texture = NULL;
11438         }
11439
11440         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11441
11442 //      R_Mesh_ResetTextureState();
11443         R_SetupShader_Generic_NoTexture(false, false);
11444         GL_DepthRange(0, 1);
11445         GL_DepthTest(!r_showdisabledepthtest.integer);
11446         GL_DepthMask(false);
11447         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11448
11449         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11450         {
11451                 int triangleindex;
11452                 int bihleafindex;
11453                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11454                 const q3mbrush_t *brush;
11455                 const bih_t *bih = &model->collision_bih;
11456                 const bih_leaf_t *bihleaf;
11457                 float vertex3f[3][3];
11458                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11459                 cullbox = false;
11460                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11461                 {
11462                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11463                                 continue;
11464                         switch (bihleaf->type)
11465                         {
11466                         case BIH_BRUSH:
11467                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11468                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11469                                 {
11470                                         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);
11471                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11472                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11473                                 }
11474                                 break;
11475                         case BIH_COLLISIONTRIANGLE:
11476                                 triangleindex = bihleaf->itemindex;
11477                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11478                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11479                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11480                                 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);
11481                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11482                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11483                                 break;
11484                         case BIH_RENDERTRIANGLE:
11485                                 triangleindex = bihleaf->itemindex;
11486                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11487                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11488                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11489                                 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);
11490                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11491                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11492                                 break;
11493                         }
11494                 }
11495         }
11496
11497         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11498
11499 #ifndef USE_GLES2
11500         if (r_showtris.integer && qglPolygonMode)
11501         {
11502                 if (r_showdisabledepthtest.integer)
11503                 {
11504                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11505                         GL_DepthMask(false);
11506                 }
11507                 else
11508                 {
11509                         GL_BlendFunc(GL_ONE, GL_ZERO);
11510                         GL_DepthMask(true);
11511                 }
11512                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11513                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11514                 {
11515                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11516                                 continue;
11517                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11518                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11519                         {
11520                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11521                                 if (!rsurface.texture->currentlayers->depthmask)
11522                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11523                                 else if (ent == r_refdef.scene.worldentity)
11524                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11525                                 else
11526                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11527                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11528                                 RSurf_DrawBatch();
11529                         }
11530                 }
11531                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11532                 rsurface.texture = NULL;
11533         }
11534
11535         if (r_shownormals.value != 0 && qglBegin)
11536         {
11537                 if (r_showdisabledepthtest.integer)
11538                 {
11539                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11540                         GL_DepthMask(false);
11541                 }
11542                 else
11543                 {
11544                         GL_BlendFunc(GL_ONE, GL_ZERO);
11545                         GL_DepthMask(true);
11546                 }
11547                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11548                 {
11549                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11550                                 continue;
11551                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11552                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11553                         {
11554                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11555                                 qglBegin(GL_LINES);
11556                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11557                                 {
11558                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11559                                         {
11560                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11561                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11562                                                 qglVertex3f(v[0], v[1], v[2]);
11563                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11564                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11565                                                 qglVertex3f(v[0], v[1], v[2]);
11566                                         }
11567                                 }
11568                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11569                                 {
11570                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11571                                         {
11572                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11573                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11574                                                 qglVertex3f(v[0], v[1], v[2]);
11575                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11576                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11577                                                 qglVertex3f(v[0], v[1], v[2]);
11578                                         }
11579                                 }
11580                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11581                                 {
11582                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11583                                         {
11584                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11585                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11586                                                 qglVertex3f(v[0], v[1], v[2]);
11587                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11588                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11589                                                 qglVertex3f(v[0], v[1], v[2]);
11590                                         }
11591                                 }
11592                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11593                                 {
11594                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11595                                         {
11596                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11597                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11598                                                 qglVertex3f(v[0], v[1], v[2]);
11599                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11600                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11601                                                 qglVertex3f(v[0], v[1], v[2]);
11602                                         }
11603                                 }
11604                                 qglEnd();
11605                                 CHECKGLERROR
11606                         }
11607                 }
11608                 rsurface.texture = NULL;
11609         }
11610 #endif
11611 }
11612
11613 int r_maxsurfacelist = 0;
11614 const msurface_t **r_surfacelist = NULL;
11615 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11616 {
11617         int i, j, endj, flagsmask;
11618         dp_model_t *model = r_refdef.scene.worldmodel;
11619         msurface_t *surfaces;
11620         unsigned char *update;
11621         int numsurfacelist = 0;
11622         if (model == NULL)
11623                 return;
11624
11625         if (r_maxsurfacelist < model->num_surfaces)
11626         {
11627                 r_maxsurfacelist = model->num_surfaces;
11628                 if (r_surfacelist)
11629                         Mem_Free((msurface_t**)r_surfacelist);
11630                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11631         }
11632
11633         RSurf_ActiveWorldEntity();
11634
11635         surfaces = model->data_surfaces;
11636         update = model->brushq1.lightmapupdateflags;
11637
11638         // update light styles on this submodel
11639         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11640         {
11641                 model_brush_lightstyleinfo_t *style;
11642                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11643                 {
11644                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11645                         {
11646                                 int *list = style->surfacelist;
11647                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11648                                 for (j = 0;j < style->numsurfaces;j++)
11649                                         update[list[j]] = true;
11650                         }
11651                 }
11652         }
11653
11654         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11655
11656         if (debug)
11657         {
11658                 R_DrawDebugModel();
11659                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11660                 return;
11661         }
11662
11663         rsurface.lightmaptexture = NULL;
11664         rsurface.deluxemaptexture = NULL;
11665         rsurface.uselightmaptexture = false;
11666         rsurface.texture = NULL;
11667         rsurface.rtlight = NULL;
11668         numsurfacelist = 0;
11669         // add visible surfaces to draw list
11670         for (i = 0;i < model->nummodelsurfaces;i++)
11671         {
11672                 j = model->sortedmodelsurfaces[i];
11673                 if (r_refdef.viewcache.world_surfacevisible[j])
11674                         r_surfacelist[numsurfacelist++] = surfaces + j;
11675         }
11676         // update lightmaps if needed
11677         if (model->brushq1.firstrender)
11678         {
11679                 model->brushq1.firstrender = false;
11680                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11681                         if (update[j])
11682                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11683         }
11684         else if (update)
11685         {
11686                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11687                         if (r_refdef.viewcache.world_surfacevisible[j])
11688                                 if (update[j])
11689                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11690         }
11691         // don't do anything if there were no surfaces
11692         if (!numsurfacelist)
11693         {
11694                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11695                 return;
11696         }
11697         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11698
11699         // add to stats if desired
11700         if (r_speeds.integer && !skysurfaces && !depthonly)
11701         {
11702                 r_refdef.stats.world_surfaces += numsurfacelist;
11703                 for (j = 0;j < numsurfacelist;j++)
11704                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11705         }
11706
11707         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11708 }
11709
11710 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11711 {
11712         int i, j, endj, flagsmask;
11713         dp_model_t *model = ent->model;
11714         msurface_t *surfaces;
11715         unsigned char *update;
11716         int numsurfacelist = 0;
11717         if (model == NULL)
11718                 return;
11719
11720         if (r_maxsurfacelist < model->num_surfaces)
11721         {
11722                 r_maxsurfacelist = model->num_surfaces;
11723                 if (r_surfacelist)
11724                         Mem_Free((msurface_t **)r_surfacelist);
11725                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11726         }
11727
11728         // if the model is static it doesn't matter what value we give for
11729         // wantnormals and wanttangents, so this logic uses only rules applicable
11730         // to a model, knowing that they are meaningless otherwise
11731         if (ent == r_refdef.scene.worldentity)
11732                 RSurf_ActiveWorldEntity();
11733         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11734                 RSurf_ActiveModelEntity(ent, false, false, false);
11735         else if (prepass)
11736                 RSurf_ActiveModelEntity(ent, true, true, true);
11737         else if (depthonly)
11738         {
11739                 switch (vid.renderpath)
11740                 {
11741                 case RENDERPATH_GL20:
11742                 case RENDERPATH_D3D9:
11743                 case RENDERPATH_D3D10:
11744                 case RENDERPATH_D3D11:
11745                 case RENDERPATH_SOFT:
11746                 case RENDERPATH_GLES2:
11747                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11748                         break;
11749                 case RENDERPATH_GL11:
11750                 case RENDERPATH_GL13:
11751                 case RENDERPATH_GLES1:
11752                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11753                         break;
11754                 }
11755         }
11756         else
11757         {
11758                 switch (vid.renderpath)
11759                 {
11760                 case RENDERPATH_GL20:
11761                 case RENDERPATH_D3D9:
11762                 case RENDERPATH_D3D10:
11763                 case RENDERPATH_D3D11:
11764                 case RENDERPATH_SOFT:
11765                 case RENDERPATH_GLES2:
11766                         RSurf_ActiveModelEntity(ent, true, true, false);
11767                         break;
11768                 case RENDERPATH_GL11:
11769                 case RENDERPATH_GL13:
11770                 case RENDERPATH_GLES1:
11771                         RSurf_ActiveModelEntity(ent, true, false, false);
11772                         break;
11773                 }
11774         }
11775
11776         surfaces = model->data_surfaces;
11777         update = model->brushq1.lightmapupdateflags;
11778
11779         // update light styles
11780         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11781         {
11782                 model_brush_lightstyleinfo_t *style;
11783                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11784                 {
11785                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11786                         {
11787                                 int *list = style->surfacelist;
11788                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11789                                 for (j = 0;j < style->numsurfaces;j++)
11790                                         update[list[j]] = true;
11791                         }
11792                 }
11793         }
11794
11795         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11796
11797         if (debug)
11798         {
11799                 R_DrawDebugModel();
11800                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11801                 return;
11802         }
11803
11804         rsurface.lightmaptexture = NULL;
11805         rsurface.deluxemaptexture = NULL;
11806         rsurface.uselightmaptexture = false;
11807         rsurface.texture = NULL;
11808         rsurface.rtlight = NULL;
11809         numsurfacelist = 0;
11810         // add visible surfaces to draw list
11811         for (i = 0;i < model->nummodelsurfaces;i++)
11812                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11813         // don't do anything if there were no surfaces
11814         if (!numsurfacelist)
11815         {
11816                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11817                 return;
11818         }
11819         // update lightmaps if needed
11820         if (update)
11821         {
11822                 int updated = 0;
11823                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11824                 {
11825                         if (update[j])
11826                         {
11827                                 updated++;
11828                                 R_BuildLightMap(ent, surfaces + j);
11829                         }
11830                 }
11831         }
11832         if (update)
11833                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11834                         if (update[j])
11835                                 R_BuildLightMap(ent, surfaces + j);
11836         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11837
11838         // add to stats if desired
11839         if (r_speeds.integer && !skysurfaces && !depthonly)
11840         {
11841                 r_refdef.stats.entities_surfaces += numsurfacelist;
11842                 for (j = 0;j < numsurfacelist;j++)
11843                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11844         }
11845
11846         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11847 }
11848
11849 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11850 {
11851         static texture_t texture;
11852         static msurface_t surface;
11853         const msurface_t *surfacelist = &surface;
11854
11855         // fake enough texture and surface state to render this geometry
11856
11857         texture.update_lastrenderframe = -1; // regenerate this texture
11858         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11859         texture.currentskinframe = skinframe;
11860         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11861         texture.offsetmapping = OFFSETMAPPING_OFF;
11862         texture.offsetscale = 1;
11863         texture.specularscalemod = 1;
11864         texture.specularpowermod = 1;
11865
11866         surface.texture = &texture;
11867         surface.num_triangles = numtriangles;
11868         surface.num_firsttriangle = firsttriangle;
11869         surface.num_vertices = numvertices;
11870         surface.num_firstvertex = firstvertex;
11871
11872         // now render it
11873         rsurface.texture = R_GetCurrentTexture(surface.texture);
11874         rsurface.lightmaptexture = NULL;
11875         rsurface.deluxemaptexture = NULL;
11876         rsurface.uselightmaptexture = false;
11877         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11878 }
11879
11880 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)
11881 {
11882         static msurface_t surface;
11883         const msurface_t *surfacelist = &surface;
11884
11885         // fake enough texture and surface state to render this geometry
11886         surface.texture = texture;
11887         surface.num_triangles = numtriangles;
11888         surface.num_firsttriangle = firsttriangle;
11889         surface.num_vertices = numvertices;
11890         surface.num_firstvertex = firstvertex;
11891
11892         // now render it
11893         rsurface.texture = R_GetCurrentTexture(surface.texture);
11894         rsurface.lightmaptexture = NULL;
11895         rsurface.deluxemaptexture = NULL;
11896         rsurface.uselightmaptexture = false;
11897         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11898 }