]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
default r_usedepthtextures to 1 until issues are resolved with its
[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_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
81 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
82 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)"};
83 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
84 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
85 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"};
86 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"};
87 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
88 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"};
89 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"};
90 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"};
91 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
92 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
93 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
94 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
95 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
96 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
97 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
98 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)"};
99 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)"};
100 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
101 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
102 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
103 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
104 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
105
106 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
107 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
108 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
109
110 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
111 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
112 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
113 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."};
114 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
115 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
116 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
117 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."};
118 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
119 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
120 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
121 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
122 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"};
123 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"};
124 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
125 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
126 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
127 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
128 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
129 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"};
130 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
131 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
132 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
133
134 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
135 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
136 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
137 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
138 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
139 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
140 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
141 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
142
143 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)"};
144 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"};
145
146 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
147 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
148 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
149
150 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"};
151 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"};
152 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"};
153 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
154 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
155 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"};
156 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)"};
157 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)"};
158 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
159
160 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)"};
161 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
162 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)"};
163 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
164 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)"};
165 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)"};
166 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
167 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"};
168 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."};
169 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
170 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)"};
171 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)"};
172 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)"};
173 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)"};
174 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)"};
175 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)"};
176 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)"};
177 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)"};
178
179 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)"};
180 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
181 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"};
182 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
183 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
184 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
185 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"};
186 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"};
187 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)"};
188
189 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
190 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
191 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
192 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
193
194 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
195 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
196
197 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
198 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
199 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
200 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
201 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
202
203 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
204 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
205 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
206 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
207 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
208 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
209 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
210 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
211 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
212 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
213
214 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"};
215
216 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"};
217
218 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
219
220 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
221
222 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
223 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"};
224
225 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."};
226
227 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)"};
228
229 extern cvar_t v_glslgamma;
230 extern cvar_t v_glslgamma_2d;
231
232 extern qboolean v_flipped_state;
233
234 r_framebufferstate_t r_fb;
235
236 /// shadow volume bsp struct with automatically growing nodes buffer
237 svbsp_t r_svbsp;
238
239 rtexture_t *r_texture_blanknormalmap;
240 rtexture_t *r_texture_white;
241 rtexture_t *r_texture_grey128;
242 rtexture_t *r_texture_black;
243 rtexture_t *r_texture_notexture;
244 rtexture_t *r_texture_whitecube;
245 rtexture_t *r_texture_normalizationcube;
246 rtexture_t *r_texture_fogattenuation;
247 rtexture_t *r_texture_fogheighttexture;
248 rtexture_t *r_texture_gammaramps;
249 unsigned int r_texture_gammaramps_serial;
250 //rtexture_t *r_texture_fogintensity;
251 rtexture_t *r_texture_reflectcube;
252
253 // TODO: hash lookups?
254 typedef struct cubemapinfo_s
255 {
256         char basename[64];
257         rtexture_t *texture;
258 }
259 cubemapinfo_t;
260
261 int r_texture_numcubemaps;
262 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
263
264 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
265 unsigned int r_numqueries;
266 unsigned int r_maxqueries;
267
268 typedef struct r_qwskincache_s
269 {
270         char name[MAX_QPATH];
271         skinframe_t *skinframe;
272 }
273 r_qwskincache_t;
274
275 static r_qwskincache_t *r_qwskincache;
276 static int r_qwskincache_size;
277
278 /// vertex coordinates for a quad that covers the screen exactly
279 extern const float r_screenvertex3f[12];
280 extern const float r_d3dscreenvertex3f[12];
281 const float r_screenvertex3f[12] =
282 {
283         0, 0, 0,
284         1, 0, 0,
285         1, 1, 0,
286         0, 1, 0
287 };
288 const float r_d3dscreenvertex3f[12] =
289 {
290         0, 1, 0,
291         1, 1, 0,
292         1, 0, 0,
293         0, 0, 0
294 };
295
296 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
297 {
298         int i;
299         for (i = 0;i < verts;i++)
300         {
301                 out[0] = in[0] * r;
302                 out[1] = in[1] * g;
303                 out[2] = in[2] * b;
304                 out[3] = in[3];
305                 in += 4;
306                 out += 4;
307         }
308 }
309
310 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
311 {
312         int i;
313         for (i = 0;i < verts;i++)
314         {
315                 out[0] = r;
316                 out[1] = g;
317                 out[2] = b;
318                 out[3] = a;
319                 out += 4;
320         }
321 }
322
323 // FIXME: move this to client?
324 void FOG_clear(void)
325 {
326         if (gamemode == GAME_NEHAHRA)
327         {
328                 Cvar_Set("gl_fogenable", "0");
329                 Cvar_Set("gl_fogdensity", "0.2");
330                 Cvar_Set("gl_fogred", "0.3");
331                 Cvar_Set("gl_foggreen", "0.3");
332                 Cvar_Set("gl_fogblue", "0.3");
333         }
334         r_refdef.fog_density = 0;
335         r_refdef.fog_red = 0;
336         r_refdef.fog_green = 0;
337         r_refdef.fog_blue = 0;
338         r_refdef.fog_alpha = 1;
339         r_refdef.fog_start = 0;
340         r_refdef.fog_end = 16384;
341         r_refdef.fog_height = 1<<30;
342         r_refdef.fog_fadedepth = 128;
343         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
344 }
345
346 static void R_BuildBlankTextures(void)
347 {
348         unsigned char data[4];
349         data[2] = 128; // normal X
350         data[1] = 128; // normal Y
351         data[0] = 255; // normal Z
352         data[3] = 255; // height
353         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
354         data[0] = 255;
355         data[1] = 255;
356         data[2] = 255;
357         data[3] = 255;
358         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
359         data[0] = 128;
360         data[1] = 128;
361         data[2] = 128;
362         data[3] = 255;
363         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
364         data[0] = 0;
365         data[1] = 0;
366         data[2] = 0;
367         data[3] = 255;
368         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
369 }
370
371 static void R_BuildNoTexture(void)
372 {
373         int x, y;
374         unsigned char pix[16][16][4];
375         // this makes a light grey/dark grey checkerboard texture
376         for (y = 0;y < 16;y++)
377         {
378                 for (x = 0;x < 16;x++)
379                 {
380                         if ((y < 8) ^ (x < 8))
381                         {
382                                 pix[y][x][0] = 128;
383                                 pix[y][x][1] = 128;
384                                 pix[y][x][2] = 128;
385                                 pix[y][x][3] = 255;
386                         }
387                         else
388                         {
389                                 pix[y][x][0] = 64;
390                                 pix[y][x][1] = 64;
391                                 pix[y][x][2] = 64;
392                                 pix[y][x][3] = 255;
393                         }
394                 }
395         }
396         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
397 }
398
399 static void R_BuildWhiteCube(void)
400 {
401         unsigned char data[6*1*1*4];
402         memset(data, 255, sizeof(data));
403         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
404 }
405
406 static void R_BuildNormalizationCube(void)
407 {
408         int x, y, side;
409         vec3_t v;
410         vec_t s, t, intensity;
411 #define NORMSIZE 64
412         unsigned char *data;
413         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
414         for (side = 0;side < 6;side++)
415         {
416                 for (y = 0;y < NORMSIZE;y++)
417                 {
418                         for (x = 0;x < NORMSIZE;x++)
419                         {
420                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
421                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
422                                 switch(side)
423                                 {
424                                 default:
425                                 case 0:
426                                         v[0] = 1;
427                                         v[1] = -t;
428                                         v[2] = -s;
429                                         break;
430                                 case 1:
431                                         v[0] = -1;
432                                         v[1] = -t;
433                                         v[2] = s;
434                                         break;
435                                 case 2:
436                                         v[0] = s;
437                                         v[1] = 1;
438                                         v[2] = t;
439                                         break;
440                                 case 3:
441                                         v[0] = s;
442                                         v[1] = -1;
443                                         v[2] = -t;
444                                         break;
445                                 case 4:
446                                         v[0] = s;
447                                         v[1] = -t;
448                                         v[2] = 1;
449                                         break;
450                                 case 5:
451                                         v[0] = -s;
452                                         v[1] = -t;
453                                         v[2] = -1;
454                                         break;
455                                 }
456                                 intensity = 127.0f / sqrt(DotProduct(v, v));
457                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
458                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
459                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
460                                 data[((side*64+y)*64+x)*4+3] = 255;
461                         }
462                 }
463         }
464         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
465         Mem_Free(data);
466 }
467
468 static void R_BuildFogTexture(void)
469 {
470         int x, b;
471 #define FOGWIDTH 256
472         unsigned char data1[FOGWIDTH][4];
473         //unsigned char data2[FOGWIDTH][4];
474         double d, r, alpha;
475
476         r_refdef.fogmasktable_start = r_refdef.fog_start;
477         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
478         r_refdef.fogmasktable_range = r_refdef.fogrange;
479         r_refdef.fogmasktable_density = r_refdef.fog_density;
480
481         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
482         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
483         {
484                 d = (x * r - r_refdef.fogmasktable_start);
485                 if(developer_extra.integer)
486                         Con_DPrintf("%f ", d);
487                 d = max(0, d);
488                 if (r_fog_exp2.integer)
489                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
490                 else
491                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
492                 if(developer_extra.integer)
493                         Con_DPrintf(" : %f ", alpha);
494                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
495                 if(developer_extra.integer)
496                         Con_DPrintf(" = %f\n", alpha);
497                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
498         }
499
500         for (x = 0;x < FOGWIDTH;x++)
501         {
502                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
503                 data1[x][0] = b;
504                 data1[x][1] = b;
505                 data1[x][2] = b;
506                 data1[x][3] = 255;
507                 //data2[x][0] = 255 - b;
508                 //data2[x][1] = 255 - b;
509                 //data2[x][2] = 255 - b;
510                 //data2[x][3] = 255;
511         }
512         if (r_texture_fogattenuation)
513         {
514                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
515                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
516         }
517         else
518         {
519                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
520                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
521         }
522 }
523
524 static void R_BuildFogHeightTexture(void)
525 {
526         unsigned char *inpixels;
527         int size;
528         int x;
529         int y;
530         int j;
531         float c[4];
532         float f;
533         inpixels = NULL;
534         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
535         if (r_refdef.fogheighttexturename[0])
536                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
537         if (!inpixels)
538         {
539                 r_refdef.fog_height_tablesize = 0;
540                 if (r_texture_fogheighttexture)
541                         R_FreeTexture(r_texture_fogheighttexture);
542                 r_texture_fogheighttexture = NULL;
543                 if (r_refdef.fog_height_table2d)
544                         Mem_Free(r_refdef.fog_height_table2d);
545                 r_refdef.fog_height_table2d = NULL;
546                 if (r_refdef.fog_height_table1d)
547                         Mem_Free(r_refdef.fog_height_table1d);
548                 r_refdef.fog_height_table1d = NULL;
549                 return;
550         }
551         size = image_width;
552         r_refdef.fog_height_tablesize = size;
553         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
554         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
555         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
556         Mem_Free(inpixels);
557         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
558         // average fog color table accounting for every fog layer between a point
559         // and the camera.  (Note: attenuation is handled separately!)
560         for (y = 0;y < size;y++)
561         {
562                 for (x = 0;x < size;x++)
563                 {
564                         Vector4Clear(c);
565                         f = 0;
566                         if (x < y)
567                         {
568                                 for (j = x;j <= y;j++)
569                                 {
570                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
571                                         f++;
572                                 }
573                         }
574                         else
575                         {
576                                 for (j = x;j >= y;j--)
577                                 {
578                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
579                                         f++;
580                                 }
581                         }
582                         f = 1.0f / f;
583                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
584                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
585                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
586                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
587                 }
588         }
589         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
590 }
591
592 //=======================================================================================================================================================
593
594 static const char *builtinshaderstring =
595 #include "shader_glsl.h"
596 ;
597
598 const char *builtinhlslshaderstring =
599 #include "shader_hlsl.h"
600 ;
601
602 char *glslshaderstring = NULL;
603 char *hlslshaderstring = NULL;
604
605 //=======================================================================================================================================================
606
607 typedef struct shaderpermutationinfo_s
608 {
609         const char *pretext;
610         const char *name;
611 }
612 shaderpermutationinfo_t;
613
614 typedef struct shadermodeinfo_s
615 {
616         const char *vertexfilename;
617         const char *geometryfilename;
618         const char *fragmentfilename;
619         const char *pretext;
620         const char *name;
621 }
622 shadermodeinfo_t;
623
624 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
625 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
626 {
627         {"#define USEDIFFUSE\n", " diffuse"},
628         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
629         {"#define USEVIEWTINT\n", " viewtint"},
630         {"#define USECOLORMAPPING\n", " colormapping"},
631         {"#define USESATURATION\n", " saturation"},
632         {"#define USEFOGINSIDE\n", " foginside"},
633         {"#define USEFOGOUTSIDE\n", " fogoutside"},
634         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
635         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
636         {"#define USEGAMMARAMPS\n", " gammaramps"},
637         {"#define USECUBEFILTER\n", " cubefilter"},
638         {"#define USEGLOW\n", " glow"},
639         {"#define USEBLOOM\n", " bloom"},
640         {"#define USESPECULAR\n", " specular"},
641         {"#define USEPOSTPROCESSING\n", " postprocessing"},
642         {"#define USEREFLECTION\n", " reflection"},
643         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
644         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
645         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
646         {"#define USESHADOWMAPPCF 1\n", " shadowmappcf"}, // TODO make this a static parm
647         {"#define USESHADOWMAPPCF 2\n", " shadowmappcf2"}, // TODO make this a static parm
648         {"#define USESHADOWSAMPLER\n", " shadowsampler"}, // TODO make this a static parm
649         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
650         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
651         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
652         {"#define USEALPHAKILL\n", " alphakill"},
653         {"#define USEREFLECTCUBE\n", " reflectcube"},
654         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
655         {"#define USEBOUNCEGRID\n", " bouncegrid"},
656         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
657         {"#define USETRIPPY\n", " trippy"},
658         {"#define USEDEPTHRGB\n", " depthrgb"},
659 };
660
661 // NOTE: MUST MATCH ORDER OF SHADERMODE_* ENUMS!
662 shadermodeinfo_t glslshadermodeinfo[SHADERMODE_COUNT] =
663 {
664         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_GENERIC\n", " generic"},
665         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_POSTPROCESS\n", " postprocess"},
666         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
667         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
668         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
669         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTMAP\n", " lightmap"},
670         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_FAKELIGHT\n", " fakelight"},
671         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
672         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
673         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
674         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
675         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
676         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
677         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_REFRACTION\n", " refraction"},
678         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_WATER\n", " water"},
679         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
680         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
681         {"glsl/default.glsl", NULL, "glsl/default.glsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
682 };
683
684 shadermodeinfo_t hlslshadermodeinfo[SHADERMODE_COUNT] =
685 {
686         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_GENERIC\n", " generic"},
687         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_POSTPROCESS\n", " postprocess"},
688         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEPTH_OR_SHADOW\n", " depth/shadow"},
689         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FLATCOLOR\n", " flatcolor"},
690         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_VERTEXCOLOR\n", " vertexcolor"},
691         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTMAP\n", " lightmap"},
692         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_FAKELIGHT\n", " fakelight"},
693         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_MODELSPACE\n", " lightdirectionmap_modelspace"},
694         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_TANGENTSPACE\n", " lightdirectionmap_tangentspace"},
695         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP\n", " lightdirectionmap_forced_lightmap"},
696         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR\n", " lightdirectionmap_forced_vertexcolor"},
697         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTDIRECTION\n", " lightdirection"},
698         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_LIGHTSOURCE\n", " lightsource"},
699         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_REFRACTION\n", " refraction"},
700         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_WATER\n", " water"},
701         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_SHOWDEPTH\n", " showdepth"},
702         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDGEOMETRY\n", " deferredgeometry"},
703         {"hlsl/default.hlsl", NULL, "hlsl/default.hlsl", "#define MODE_DEFERREDLIGHTSOURCE\n", " deferredlightsource"},
704 };
705
706 struct r_glsl_permutation_s;
707 typedef struct r_glsl_permutation_s
708 {
709         /// hash lookup data
710         struct r_glsl_permutation_s *hashnext;
711         unsigned int mode;
712         unsigned int permutation;
713
714         /// indicates if we have tried compiling this permutation already
715         qboolean compiled;
716         /// 0 if compilation failed
717         int program;
718         // texture units assigned to each detected uniform
719         int tex_Texture_First;
720         int tex_Texture_Second;
721         int tex_Texture_GammaRamps;
722         int tex_Texture_Normal;
723         int tex_Texture_Color;
724         int tex_Texture_Gloss;
725         int tex_Texture_Glow;
726         int tex_Texture_SecondaryNormal;
727         int tex_Texture_SecondaryColor;
728         int tex_Texture_SecondaryGloss;
729         int tex_Texture_SecondaryGlow;
730         int tex_Texture_Pants;
731         int tex_Texture_Shirt;
732         int tex_Texture_FogHeightTexture;
733         int tex_Texture_FogMask;
734         int tex_Texture_Lightmap;
735         int tex_Texture_Deluxemap;
736         int tex_Texture_Attenuation;
737         int tex_Texture_Cube;
738         int tex_Texture_Refraction;
739         int tex_Texture_Reflection;
740         int tex_Texture_ShadowMap2D;
741         int tex_Texture_CubeProjection;
742         int tex_Texture_ScreenNormalMap;
743         int tex_Texture_ScreenDiffuse;
744         int tex_Texture_ScreenSpecular;
745         int tex_Texture_ReflectMask;
746         int tex_Texture_ReflectCube;
747         int tex_Texture_BounceGrid;
748         /// locations of detected uniforms in program object, or -1 if not found
749         int loc_Texture_First;
750         int loc_Texture_Second;
751         int loc_Texture_GammaRamps;
752         int loc_Texture_Normal;
753         int loc_Texture_Color;
754         int loc_Texture_Gloss;
755         int loc_Texture_Glow;
756         int loc_Texture_SecondaryNormal;
757         int loc_Texture_SecondaryColor;
758         int loc_Texture_SecondaryGloss;
759         int loc_Texture_SecondaryGlow;
760         int loc_Texture_Pants;
761         int loc_Texture_Shirt;
762         int loc_Texture_FogHeightTexture;
763         int loc_Texture_FogMask;
764         int loc_Texture_Lightmap;
765         int loc_Texture_Deluxemap;
766         int loc_Texture_Attenuation;
767         int loc_Texture_Cube;
768         int loc_Texture_Refraction;
769         int loc_Texture_Reflection;
770         int loc_Texture_ShadowMap2D;
771         int loc_Texture_CubeProjection;
772         int loc_Texture_ScreenNormalMap;
773         int loc_Texture_ScreenDiffuse;
774         int loc_Texture_ScreenSpecular;
775         int loc_Texture_ReflectMask;
776         int loc_Texture_ReflectCube;
777         int loc_Texture_BounceGrid;
778         int loc_Alpha;
779         int loc_BloomBlur_Parameters;
780         int loc_ClientTime;
781         int loc_Color_Ambient;
782         int loc_Color_Diffuse;
783         int loc_Color_Specular;
784         int loc_Color_Glow;
785         int loc_Color_Pants;
786         int loc_Color_Shirt;
787         int loc_DeferredColor_Ambient;
788         int loc_DeferredColor_Diffuse;
789         int loc_DeferredColor_Specular;
790         int loc_DeferredMod_Diffuse;
791         int loc_DeferredMod_Specular;
792         int loc_DistortScaleRefractReflect;
793         int loc_EyePosition;
794         int loc_FogColor;
795         int loc_FogHeightFade;
796         int loc_FogPlane;
797         int loc_FogPlaneViewDist;
798         int loc_FogRangeRecip;
799         int loc_LightColor;
800         int loc_LightDir;
801         int loc_LightPosition;
802         int loc_OffsetMapping_ScaleSteps;
803         int loc_OffsetMapping_LodDistance;
804         int loc_OffsetMapping_Bias;
805         int loc_PixelSize;
806         int loc_ReflectColor;
807         int loc_ReflectFactor;
808         int loc_ReflectOffset;
809         int loc_RefractColor;
810         int loc_Saturation;
811         int loc_ScreenCenterRefractReflect;
812         int loc_ScreenScaleRefractReflect;
813         int loc_ScreenToDepth;
814         int loc_ShadowMap_Parameters;
815         int loc_ShadowMap_TextureScale;
816         int loc_SpecularPower;
817         int loc_UserVec1;
818         int loc_UserVec2;
819         int loc_UserVec3;
820         int loc_UserVec4;
821         int loc_ViewTintColor;
822         int loc_ViewToLight;
823         int loc_ModelToLight;
824         int loc_TexMatrix;
825         int loc_BackgroundTexMatrix;
826         int loc_ModelViewProjectionMatrix;
827         int loc_ModelViewMatrix;
828         int loc_PixelToScreenTexCoord;
829         int loc_ModelToReflectCube;
830         int loc_ShadowMapMatrix;
831         int loc_BloomColorSubtract;
832         int loc_NormalmapScrollBlend;
833         int loc_BounceGridMatrix;
834         int loc_BounceGridIntensity;
835 }
836 r_glsl_permutation_t;
837
838 #define SHADERPERMUTATION_HASHSIZE 256
839
840
841 // non-degradable "lightweight" shader parameters to keep the permutations simpler
842 // these can NOT degrade! only use for simple stuff
843 enum
844 {
845         SHADERSTATICPARM_SATURATION_REDCOMPENSATE = 0, ///< red compensation filter for saturation
846         SHADERSTATICPARM_EXACTSPECULARMATH = 1, ///< (lightsource or deluxemapping) use exact reflection map for specular effects, as opposed to the usual OpenGL approximation
847         SHADERSTATICPARM_POSTPROCESS_USERVEC1 = 2, ///< postprocess uservec1 is enabled
848         SHADERSTATICPARM_POSTPROCESS_USERVEC2 = 3, ///< postprocess uservec2 is enabled
849         SHADERSTATICPARM_POSTPROCESS_USERVEC3 = 4, ///< postprocess uservec3 is enabled
850         SHADERSTATICPARM_POSTPROCESS_USERVEC4 = 5,  ///< postprocess uservec4 is enabled
851         SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS = 6, // use both alpha layers while blending materials, allows more advanced microblending
852         SHADERSTATICPARM_OFFSETMAPPING_USELOD = 7,  ///< LOD for offsetmapping
853 };
854 #define SHADERSTATICPARMS_COUNT 8
855
856 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
857 static int shaderstaticparms_count = 0;
858
859 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
860 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
861 static qboolean R_CompileShader_CheckStaticParms(void)
862 {
863         static int r_compileshader_staticparms_save[1];
864         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
865         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
866
867         // detect all
868         if (r_glsl_saturation_redcompensate.integer)
869                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
870         if (r_glsl_vertextextureblend_usebothalphas.integer)
871                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
872         if (r_shadow_glossexact.integer)
873                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
874         if (r_glsl_postprocess.integer)
875         {
876                 if (r_glsl_postprocess_uservec1_enable.integer)
877                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
878                 if (r_glsl_postprocess_uservec2_enable.integer)
879                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
880                 if (r_glsl_postprocess_uservec3_enable.integer)
881                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
882                 if (r_glsl_postprocess_uservec4_enable.integer)
883                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
884         }
885         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
886                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
887         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
888 }
889
890 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
891         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
892                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
893         else \
894                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
895 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
896 {
897         shaderstaticparms_count = 0;
898
899         // emit all
900         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
901         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
902         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
903         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
904         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
905         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
906         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
907         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
908 }
909
910 /// information about each possible shader permutation
911 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
912 /// currently selected permutation
913 r_glsl_permutation_t *r_glsl_permutation;
914 /// storage for permutations linked in the hash table
915 memexpandablearray_t r_glsl_permutationarray;
916
917 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
918 {
919         //unsigned int hashdepth = 0;
920         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
921         r_glsl_permutation_t *p;
922         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
923         {
924                 if (p->mode == mode && p->permutation == permutation)
925                 {
926                         //if (hashdepth > 10)
927                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
928                         return p;
929                 }
930                 //hashdepth++;
931         }
932         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
933         p->mode = mode;
934         p->permutation = permutation;
935         p->hashnext = r_glsl_permutationhash[mode][hashindex];
936         r_glsl_permutationhash[mode][hashindex] = p;
937         //if (hashdepth > 10)
938         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
939         return p;
940 }
941
942 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
943 {
944         char *shaderstring;
945         if (!filename || !filename[0])
946                 return NULL;
947         if (!strcmp(filename, "glsl/default.glsl"))
948         {
949                 if (!glslshaderstring)
950                 {
951                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
952                         if (glslshaderstring)
953                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
954                         else
955                                 glslshaderstring = (char *)builtinshaderstring;
956                 }
957                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
958                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
959                 return shaderstring;
960         }
961         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
962         if (shaderstring)
963         {
964                 if (printfromdisknotice)
965                         Con_DPrintf("from disk %s... ", filename);
966                 return shaderstring;
967         }
968         return shaderstring;
969 }
970
971 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
972 {
973         int i;
974         int sampler;
975         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
976         char *vertexstring, *geometrystring, *fragmentstring;
977         char permutationname[256];
978         int vertstrings_count = 0;
979         int geomstrings_count = 0;
980         int fragstrings_count = 0;
981         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
982         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
983         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
984
985         if (p->compiled)
986                 return;
987         p->compiled = true;
988         p->program = 0;
989
990         permutationname[0] = 0;
991         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
992         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
993         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
994
995         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
996
997         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
998         if(vid.support.gl20shaders130)
999         {
1000                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1001                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1002                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1003                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1004                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1005                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1006         }
1007
1008         // the first pretext is which type of shader to compile as
1009         // (later these will all be bound together as a program object)
1010         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1011         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1012         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1013
1014         // the second pretext is the mode (for example a light source)
1015         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1016         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1017         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1018         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1019
1020         // now add all the permutation pretexts
1021         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1022         {
1023                 if (permutation & (1<<i))
1024                 {
1025                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1026                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1027                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1028                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1029                 }
1030                 else
1031                 {
1032                         // keep line numbers correct
1033                         vertstrings_list[vertstrings_count++] = "\n";
1034                         geomstrings_list[geomstrings_count++] = "\n";
1035                         fragstrings_list[fragstrings_count++] = "\n";
1036                 }
1037         }
1038
1039         // add static parms
1040         R_CompileShader_AddStaticParms(mode, permutation);
1041         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1042         vertstrings_count += shaderstaticparms_count;
1043         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1044         geomstrings_count += shaderstaticparms_count;
1045         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1046         fragstrings_count += shaderstaticparms_count;
1047
1048         // now append the shader text itself
1049         vertstrings_list[vertstrings_count++] = vertexstring;
1050         geomstrings_list[geomstrings_count++] = geometrystring;
1051         fragstrings_list[fragstrings_count++] = fragmentstring;
1052
1053         // if any sources were NULL, clear the respective list
1054         if (!vertexstring)
1055                 vertstrings_count = 0;
1056         if (!geometrystring)
1057                 geomstrings_count = 0;
1058         if (!fragmentstring)
1059                 fragstrings_count = 0;
1060
1061         // compile the shader program
1062         if (vertstrings_count + geomstrings_count + fragstrings_count)
1063                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1064         if (p->program)
1065         {
1066                 CHECKGLERROR
1067                 qglUseProgram(p->program);CHECKGLERROR
1068                 // look up all the uniform variable names we care about, so we don't
1069                 // have to look them up every time we set them
1070
1071                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1072                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1073                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1074                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1075                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1076                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1077                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1078                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1079                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1080                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1081                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1082                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1083                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1084                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1085                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1086                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1087                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1088                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1089                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1090                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1091                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1092                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1093                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1094                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1095                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1096                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1097                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1098                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1099                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1100                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1101                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1102                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1103                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1104                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1105                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1106                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1107                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1108                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1109                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1110                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1111                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1112                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1113                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1114                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1115                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1116                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1117                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1118                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1119                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1120                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1121                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1122                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1123                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1124                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1125                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1126                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1127                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1128                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1129                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1130                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1131                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1132                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1133                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1134                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1135                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1136                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1137                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1138                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1139                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1140                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1141                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1142                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1143                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1144                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1145                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1146                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1147                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1148                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1149                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1150                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1151                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1152                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1153                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1154                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1155                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1156                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1157                 // initialize the samplers to refer to the texture units we use
1158                 p->tex_Texture_First = -1;
1159                 p->tex_Texture_Second = -1;
1160                 p->tex_Texture_GammaRamps = -1;
1161                 p->tex_Texture_Normal = -1;
1162                 p->tex_Texture_Color = -1;
1163                 p->tex_Texture_Gloss = -1;
1164                 p->tex_Texture_Glow = -1;
1165                 p->tex_Texture_SecondaryNormal = -1;
1166                 p->tex_Texture_SecondaryColor = -1;
1167                 p->tex_Texture_SecondaryGloss = -1;
1168                 p->tex_Texture_SecondaryGlow = -1;
1169                 p->tex_Texture_Pants = -1;
1170                 p->tex_Texture_Shirt = -1;
1171                 p->tex_Texture_FogHeightTexture = -1;
1172                 p->tex_Texture_FogMask = -1;
1173                 p->tex_Texture_Lightmap = -1;
1174                 p->tex_Texture_Deluxemap = -1;
1175                 p->tex_Texture_Attenuation = -1;
1176                 p->tex_Texture_Cube = -1;
1177                 p->tex_Texture_Refraction = -1;
1178                 p->tex_Texture_Reflection = -1;
1179                 p->tex_Texture_ShadowMap2D = -1;
1180                 p->tex_Texture_CubeProjection = -1;
1181                 p->tex_Texture_ScreenNormalMap = -1;
1182                 p->tex_Texture_ScreenDiffuse = -1;
1183                 p->tex_Texture_ScreenSpecular = -1;
1184                 p->tex_Texture_ReflectMask = -1;
1185                 p->tex_Texture_ReflectCube = -1;
1186                 p->tex_Texture_BounceGrid = -1;
1187                 sampler = 0;
1188                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1189                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1190                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1191                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1192                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1193                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1194                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1195                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1196                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1197                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1198                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1199                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1200                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1201                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1202                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1203                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1204                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1205                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1206                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1207                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1208                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1209                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1210                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1211                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1212                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1213                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1214                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1215                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1216                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1217                 CHECKGLERROR
1218                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1219         }
1220         else
1221                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1222
1223         // free the strings
1224         if (vertexstring)
1225                 Mem_Free(vertexstring);
1226         if (geometrystring)
1227                 Mem_Free(geometrystring);
1228         if (fragmentstring)
1229                 Mem_Free(fragmentstring);
1230 }
1231
1232 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1233 {
1234         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1235         if (r_glsl_permutation != perm)
1236         {
1237                 r_glsl_permutation = perm;
1238                 if (!r_glsl_permutation->program)
1239                 {
1240                         if (!r_glsl_permutation->compiled)
1241                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1242                         if (!r_glsl_permutation->program)
1243                         {
1244                                 // remove features until we find a valid permutation
1245                                 int i;
1246                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1247                                 {
1248                                         // reduce i more quickly whenever it would not remove any bits
1249                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1250                                         if (!(permutation & j))
1251                                                 continue;
1252                                         permutation -= j;
1253                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1254                                         if (!r_glsl_permutation->compiled)
1255                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1256                                         if (r_glsl_permutation->program)
1257                                                 break;
1258                                 }
1259                                 if (i >= SHADERPERMUTATION_COUNT)
1260                                 {
1261                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1262                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1263                                         qglUseProgram(0);CHECKGLERROR
1264                                         return; // no bit left to clear, entire mode is broken
1265                                 }
1266                         }
1267                 }
1268                 CHECKGLERROR
1269                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1270         }
1271         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1272         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1273         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1274 }
1275
1276 #ifdef SUPPORTD3D
1277
1278 #ifdef SUPPORTD3D
1279 #include <d3d9.h>
1280 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1281 extern D3DCAPS9 vid_d3d9caps;
1282 #endif
1283
1284 struct r_hlsl_permutation_s;
1285 typedef struct r_hlsl_permutation_s
1286 {
1287         /// hash lookup data
1288         struct r_hlsl_permutation_s *hashnext;
1289         unsigned int mode;
1290         unsigned int permutation;
1291
1292         /// indicates if we have tried compiling this permutation already
1293         qboolean compiled;
1294         /// NULL if compilation failed
1295         IDirect3DVertexShader9 *vertexshader;
1296         IDirect3DPixelShader9 *pixelshader;
1297 }
1298 r_hlsl_permutation_t;
1299
1300 typedef enum D3DVSREGISTER_e
1301 {
1302         D3DVSREGISTER_TexMatrix = 0, // float4x4
1303         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1304         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1305         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1306         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1307         D3DVSREGISTER_ModelToLight = 20, // float4x4
1308         D3DVSREGISTER_EyePosition = 24,
1309         D3DVSREGISTER_FogPlane = 25,
1310         D3DVSREGISTER_LightDir = 26,
1311         D3DVSREGISTER_LightPosition = 27,
1312 }
1313 D3DVSREGISTER_t;
1314
1315 typedef enum D3DPSREGISTER_e
1316 {
1317         D3DPSREGISTER_Alpha = 0,
1318         D3DPSREGISTER_BloomBlur_Parameters = 1,
1319         D3DPSREGISTER_ClientTime = 2,
1320         D3DPSREGISTER_Color_Ambient = 3,
1321         D3DPSREGISTER_Color_Diffuse = 4,
1322         D3DPSREGISTER_Color_Specular = 5,
1323         D3DPSREGISTER_Color_Glow = 6,
1324         D3DPSREGISTER_Color_Pants = 7,
1325         D3DPSREGISTER_Color_Shirt = 8,
1326         D3DPSREGISTER_DeferredColor_Ambient = 9,
1327         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1328         D3DPSREGISTER_DeferredColor_Specular = 11,
1329         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1330         D3DPSREGISTER_DeferredMod_Specular = 13,
1331         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1332         D3DPSREGISTER_EyePosition = 15, // unused
1333         D3DPSREGISTER_FogColor = 16,
1334         D3DPSREGISTER_FogHeightFade = 17,
1335         D3DPSREGISTER_FogPlane = 18,
1336         D3DPSREGISTER_FogPlaneViewDist = 19,
1337         D3DPSREGISTER_FogRangeRecip = 20,
1338         D3DPSREGISTER_LightColor = 21,
1339         D3DPSREGISTER_LightDir = 22, // unused
1340         D3DPSREGISTER_LightPosition = 23,
1341         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1342         D3DPSREGISTER_PixelSize = 25,
1343         D3DPSREGISTER_ReflectColor = 26,
1344         D3DPSREGISTER_ReflectFactor = 27,
1345         D3DPSREGISTER_ReflectOffset = 28,
1346         D3DPSREGISTER_RefractColor = 29,
1347         D3DPSREGISTER_Saturation = 30,
1348         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1349         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1350         D3DPSREGISTER_ScreenToDepth = 33,
1351         D3DPSREGISTER_ShadowMap_Parameters = 34,
1352         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1353         D3DPSREGISTER_SpecularPower = 36,
1354         D3DPSREGISTER_UserVec1 = 37,
1355         D3DPSREGISTER_UserVec2 = 38,
1356         D3DPSREGISTER_UserVec3 = 39,
1357         D3DPSREGISTER_UserVec4 = 40,
1358         D3DPSREGISTER_ViewTintColor = 41,
1359         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1360         D3DPSREGISTER_BloomColorSubtract = 43,
1361         D3DPSREGISTER_ViewToLight = 44, // float4x4
1362         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1363         D3DPSREGISTER_NormalmapScrollBlend = 52,
1364         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1365         D3DPSREGISTER_OffsetMapping_Bias = 54,
1366         // next at 54
1367 }
1368 D3DPSREGISTER_t;
1369
1370 /// information about each possible shader permutation
1371 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1372 /// currently selected permutation
1373 r_hlsl_permutation_t *r_hlsl_permutation;
1374 /// storage for permutations linked in the hash table
1375 memexpandablearray_t r_hlsl_permutationarray;
1376
1377 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1378 {
1379         //unsigned int hashdepth = 0;
1380         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1381         r_hlsl_permutation_t *p;
1382         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1383         {
1384                 if (p->mode == mode && p->permutation == permutation)
1385                 {
1386                         //if (hashdepth > 10)
1387                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1388                         return p;
1389                 }
1390                 //hashdepth++;
1391         }
1392         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1393         p->mode = mode;
1394         p->permutation = permutation;
1395         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1396         r_hlsl_permutationhash[mode][hashindex] = p;
1397         //if (hashdepth > 10)
1398         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1399         return p;
1400 }
1401
1402 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1403 {
1404         char *shaderstring;
1405         if (!filename || !filename[0])
1406                 return NULL;
1407         if (!strcmp(filename, "hlsl/default.hlsl"))
1408         {
1409                 if (!hlslshaderstring)
1410                 {
1411                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1412                         if (hlslshaderstring)
1413                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1414                         else
1415                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1416                 }
1417                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1418                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1419                 return shaderstring;
1420         }
1421         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1422         if (shaderstring)
1423         {
1424                 if (printfromdisknotice)
1425                         Con_DPrintf("from disk %s... ", filename);
1426                 return shaderstring;
1427         }
1428         return shaderstring;
1429 }
1430
1431 #include <d3dx9.h>
1432 //#include <d3dx9shader.h>
1433 //#include <d3dx9mesh.h>
1434
1435 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1436 {
1437         DWORD *vsbin = NULL;
1438         DWORD *psbin = NULL;
1439         fs_offset_t vsbinsize;
1440         fs_offset_t psbinsize;
1441 //      IDirect3DVertexShader9 *vs = NULL;
1442 //      IDirect3DPixelShader9 *ps = NULL;
1443         ID3DXBuffer *vslog = NULL;
1444         ID3DXBuffer *vsbuffer = NULL;
1445         ID3DXConstantTable *vsconstanttable = NULL;
1446         ID3DXBuffer *pslog = NULL;
1447         ID3DXBuffer *psbuffer = NULL;
1448         ID3DXConstantTable *psconstanttable = NULL;
1449         int vsresult = 0;
1450         int psresult = 0;
1451         char temp[MAX_INPUTLINE];
1452         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1453         char vabuf[1024];
1454         qboolean debugshader = gl_paranoid.integer != 0;
1455         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1456         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1457         if (!debugshader)
1458         {
1459                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1460                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1461         }
1462         if ((!vsbin && vertstring) || (!psbin && fragstring))
1463         {
1464                 const char* dllnames_d3dx9 [] =
1465                 {
1466                         "d3dx9_43.dll",
1467                         "d3dx9_42.dll",
1468                         "d3dx9_41.dll",
1469                         "d3dx9_40.dll",
1470                         "d3dx9_39.dll",
1471                         "d3dx9_38.dll",
1472                         "d3dx9_37.dll",
1473                         "d3dx9_36.dll",
1474                         "d3dx9_35.dll",
1475                         "d3dx9_34.dll",
1476                         "d3dx9_33.dll",
1477                         "d3dx9_32.dll",
1478                         "d3dx9_31.dll",
1479                         "d3dx9_30.dll",
1480                         "d3dx9_29.dll",
1481                         "d3dx9_28.dll",
1482                         "d3dx9_27.dll",
1483                         "d3dx9_26.dll",
1484                         "d3dx9_25.dll",
1485                         "d3dx9_24.dll",
1486                         NULL
1487                 };
1488                 dllhandle_t d3dx9_dll = NULL;
1489                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1490                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1491                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1492                 dllfunction_t d3dx9_dllfuncs[] =
1493                 {
1494                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1495                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1496                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1497                         {NULL, NULL}
1498                 };
1499                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1500                 {
1501                         DWORD shaderflags = 0;
1502                         if (debugshader)
1503                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1504                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1505                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1506                         if (vertstring && vertstring[0])
1507                         {
1508                                 if (debugshader)
1509                                 {
1510 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1511 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1512                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1513                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1514                                 }
1515                                 else
1516                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1517                                 if (vsbuffer)
1518                                 {
1519                                         vsbinsize = vsbuffer->GetBufferSize();
1520                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1521                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1522                                         vsbuffer->Release();
1523                                 }
1524                                 if (vslog)
1525                                 {
1526                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1527                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1528                                         vslog->Release();
1529                                 }
1530                         }
1531                         if (fragstring && fragstring[0])
1532                         {
1533                                 if (debugshader)
1534                                 {
1535 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1536 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1537                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1538                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1539                                 }
1540                                 else
1541                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1542                                 if (psbuffer)
1543                                 {
1544                                         psbinsize = psbuffer->GetBufferSize();
1545                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1546                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1547                                         psbuffer->Release();
1548                                 }
1549                                 if (pslog)
1550                                 {
1551                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1552                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1553                                         pslog->Release();
1554                                 }
1555                         }
1556                         Sys_UnloadLibrary(&d3dx9_dll);
1557                 }
1558                 else
1559                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1560         }
1561         if (vsbin && psbin)
1562         {
1563                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1564                 if (FAILED(vsresult))
1565                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1566                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1567                 if (FAILED(psresult))
1568                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1569         }
1570         // free the shader data
1571         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1572         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1573 }
1574
1575 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1576 {
1577         int i;
1578         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1579         int vertstring_length = 0;
1580         int geomstring_length = 0;
1581         int fragstring_length = 0;
1582         char *t;
1583         char *vertexstring, *geometrystring, *fragmentstring;
1584         char *vertstring, *geomstring, *fragstring;
1585         char permutationname[256];
1586         char cachename[256];
1587         int vertstrings_count = 0;
1588         int geomstrings_count = 0;
1589         int fragstrings_count = 0;
1590         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1591         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1592         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1593
1594         if (p->compiled)
1595                 return;
1596         p->compiled = true;
1597         p->vertexshader = NULL;
1598         p->pixelshader = NULL;
1599
1600         permutationname[0] = 0;
1601         cachename[0] = 0;
1602         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1603         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1604         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1605
1606         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1607         strlcat(cachename, "hlsl/", sizeof(cachename));
1608
1609         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1610         vertstrings_count = 0;
1611         geomstrings_count = 0;
1612         fragstrings_count = 0;
1613         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1614         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1615         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1616
1617         // the first pretext is which type of shader to compile as
1618         // (later these will all be bound together as a program object)
1619         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1620         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1621         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1622
1623         // the second pretext is the mode (for example a light source)
1624         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1625         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1626         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1627         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1628         strlcat(cachename, modeinfo->name, sizeof(cachename));
1629
1630         // now add all the permutation pretexts
1631         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1632         {
1633                 if (permutation & (1<<i))
1634                 {
1635                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1636                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1637                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1638                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1639                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1640                 }
1641                 else
1642                 {
1643                         // keep line numbers correct
1644                         vertstrings_list[vertstrings_count++] = "\n";
1645                         geomstrings_list[geomstrings_count++] = "\n";
1646                         fragstrings_list[fragstrings_count++] = "\n";
1647                 }
1648         }
1649
1650         // add static parms
1651         R_CompileShader_AddStaticParms(mode, permutation);
1652         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1653         vertstrings_count += shaderstaticparms_count;
1654         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1655         geomstrings_count += shaderstaticparms_count;
1656         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1657         fragstrings_count += shaderstaticparms_count;
1658
1659         // replace spaces in the cachename with _ characters
1660         for (i = 0;cachename[i];i++)
1661                 if (cachename[i] == ' ')
1662                         cachename[i] = '_';
1663
1664         // now append the shader text itself
1665         vertstrings_list[vertstrings_count++] = vertexstring;
1666         geomstrings_list[geomstrings_count++] = geometrystring;
1667         fragstrings_list[fragstrings_count++] = fragmentstring;
1668
1669         // if any sources were NULL, clear the respective list
1670         if (!vertexstring)
1671                 vertstrings_count = 0;
1672         if (!geometrystring)
1673                 geomstrings_count = 0;
1674         if (!fragmentstring)
1675                 fragstrings_count = 0;
1676
1677         vertstring_length = 0;
1678         for (i = 0;i < vertstrings_count;i++)
1679                 vertstring_length += strlen(vertstrings_list[i]);
1680         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1681         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1682                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1683
1684         geomstring_length = 0;
1685         for (i = 0;i < geomstrings_count;i++)
1686                 geomstring_length += strlen(geomstrings_list[i]);
1687         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1688         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1689                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1690
1691         fragstring_length = 0;
1692         for (i = 0;i < fragstrings_count;i++)
1693                 fragstring_length += strlen(fragstrings_list[i]);
1694         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1695         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1696                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1697
1698         // try to load the cached shader, or generate one
1699         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1700
1701         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1702                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1703         else
1704                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1705
1706         // free the strings
1707         if (vertstring)
1708                 Mem_Free(vertstring);
1709         if (geomstring)
1710                 Mem_Free(geomstring);
1711         if (fragstring)
1712                 Mem_Free(fragstring);
1713         if (vertexstring)
1714                 Mem_Free(vertexstring);
1715         if (geometrystring)
1716                 Mem_Free(geometrystring);
1717         if (fragmentstring)
1718                 Mem_Free(fragmentstring);
1719 }
1720
1721 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1722 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1723 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);}
1724 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);}
1725 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);}
1726 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);}
1727
1728 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1729 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1730 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);}
1731 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);}
1732 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);}
1733 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);}
1734
1735 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1736 {
1737         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1738         if (r_hlsl_permutation != perm)
1739         {
1740                 r_hlsl_permutation = perm;
1741                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1742                 {
1743                         if (!r_hlsl_permutation->compiled)
1744                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1745                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1746                         {
1747                                 // remove features until we find a valid permutation
1748                                 int i;
1749                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1750                                 {
1751                                         // reduce i more quickly whenever it would not remove any bits
1752                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1753                                         if (!(permutation & j))
1754                                                 continue;
1755                                         permutation -= j;
1756                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1757                                         if (!r_hlsl_permutation->compiled)
1758                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1759                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1760                                                 break;
1761                                 }
1762                                 if (i >= SHADERPERMUTATION_COUNT)
1763                                 {
1764                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1765                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1766                                         return; // no bit left to clear, entire mode is broken
1767                                 }
1768                         }
1769                 }
1770                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1771                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1772         }
1773         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1774         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1775         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1776 }
1777 #endif
1778
1779 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1780 {
1781         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1782         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1783         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1784         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1785 }
1786
1787 static void R_GLSL_Restart_f(void)
1788 {
1789         unsigned int i, limit;
1790         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1791                 Mem_Free(glslshaderstring);
1792         glslshaderstring = NULL;
1793         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1794                 Mem_Free(hlslshaderstring);
1795         hlslshaderstring = NULL;
1796         switch(vid.renderpath)
1797         {
1798         case RENDERPATH_D3D9:
1799 #ifdef SUPPORTD3D
1800                 {
1801                         r_hlsl_permutation_t *p;
1802                         r_hlsl_permutation = NULL;
1803                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1804                         for (i = 0;i < limit;i++)
1805                         {
1806                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1807                                 {
1808                                         if (p->vertexshader)
1809                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1810                                         if (p->pixelshader)
1811                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1812                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1813                                 }
1814                         }
1815                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1816                 }
1817 #endif
1818                 break;
1819         case RENDERPATH_D3D10:
1820                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1821                 break;
1822         case RENDERPATH_D3D11:
1823                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1824                 break;
1825         case RENDERPATH_GL20:
1826         case RENDERPATH_GLES2:
1827                 {
1828                         r_glsl_permutation_t *p;
1829                         r_glsl_permutation = NULL;
1830                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1831                         for (i = 0;i < limit;i++)
1832                         {
1833                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1834                                 {
1835                                         GL_Backend_FreeProgram(p->program);
1836                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1837                                 }
1838                         }
1839                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1840                 }
1841                 break;
1842         case RENDERPATH_GL11:
1843         case RENDERPATH_GL13:
1844         case RENDERPATH_GLES1:
1845                 break;
1846         case RENDERPATH_SOFT:
1847                 break;
1848         }
1849 }
1850
1851 static void R_GLSL_DumpShader_f(void)
1852 {
1853         int i;
1854         qfile_t *file;
1855
1856         file = FS_OpenRealFile("glsl/default.glsl", "w", false);
1857         if (file)
1858         {
1859                 FS_Print(file, "/* The engine may define the following macros:\n");
1860                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1861                 for (i = 0;i < SHADERMODE_COUNT;i++)
1862                         FS_Print(file, glslshadermodeinfo[i].pretext);
1863                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1864                         FS_Print(file, shaderpermutationinfo[i].pretext);
1865                 FS_Print(file, "*/\n");
1866                 FS_Print(file, builtinshaderstring);
1867                 FS_Close(file);
1868                 Con_Printf("glsl/default.glsl written\n");
1869         }
1870         else
1871                 Con_Printf("failed to write to glsl/default.glsl\n");
1872
1873         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1874         if (file)
1875         {
1876                 FS_Print(file, "/* The engine may define the following macros:\n");
1877                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1878                 for (i = 0;i < SHADERMODE_COUNT;i++)
1879                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1880                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1881                         FS_Print(file, shaderpermutationinfo[i].pretext);
1882                 FS_Print(file, "*/\n");
1883                 FS_Print(file, builtinhlslshaderstring);
1884                 FS_Close(file);
1885                 Con_Printf("hlsl/default.hlsl written\n");
1886         }
1887         else
1888                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1889 }
1890
1891 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1892 {
1893         unsigned int permutation = 0;
1894         if (r_trippy.integer && !notrippy)
1895                 permutation |= SHADERPERMUTATION_TRIPPY;
1896         permutation |= SHADERPERMUTATION_VIEWTINT;
1897         if (first)
1898                 permutation |= SHADERPERMUTATION_DIFFUSE;
1899         if (second)
1900                 permutation |= SHADERPERMUTATION_SPECULAR;
1901         if (texturemode == GL_MODULATE)
1902                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1903         else if (texturemode == GL_ADD)
1904                 permutation |= SHADERPERMUTATION_GLOW;
1905         else if (texturemode == GL_DECAL)
1906                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1907         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1908                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1909         if (suppresstexalpha)
1910                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1911         if (!second)
1912                 texturemode = GL_MODULATE;
1913         if (vid.allowalphatocoverage)
1914                 GL_AlphaToCoverage(false);
1915         switch (vid.renderpath)
1916         {
1917         case RENDERPATH_D3D9:
1918 #ifdef SUPPORTD3D
1919                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1920                 R_Mesh_TexBind(GL20TU_FIRST , first );
1921                 R_Mesh_TexBind(GL20TU_SECOND, second);
1922                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1923                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1924 #endif
1925                 break;
1926         case RENDERPATH_D3D10:
1927                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1928                 break;
1929         case RENDERPATH_D3D11:
1930                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1931                 break;
1932         case RENDERPATH_GL20:
1933         case RENDERPATH_GLES2:
1934                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1935                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1936                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1937                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1938                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1939                 break;
1940         case RENDERPATH_GL13:
1941         case RENDERPATH_GLES1:
1942                 R_Mesh_TexBind(0, first );
1943                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1944                 R_Mesh_TexBind(1, second);
1945                 if (second)
1946                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1947                 break;
1948         case RENDERPATH_GL11:
1949                 R_Mesh_TexBind(0, first );
1950                 break;
1951         case RENDERPATH_SOFT:
1952                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1953                 R_Mesh_TexBind(GL20TU_FIRST , first );
1954                 R_Mesh_TexBind(GL20TU_SECOND, second);
1955                 break;
1956         }
1957 }
1958
1959 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1960 {
1961         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1962 }
1963
1964 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1965 {
1966         unsigned int permutation = 0;
1967         if (r_trippy.integer && !notrippy)
1968                 permutation |= SHADERPERMUTATION_TRIPPY;
1969         if (depthrgb)
1970                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1971         if (vid.allowalphatocoverage)
1972                 GL_AlphaToCoverage(false);
1973         switch (vid.renderpath)
1974         {
1975         case RENDERPATH_D3D9:
1976 #ifdef SUPPORTD3D
1977                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1978 #endif
1979                 break;
1980         case RENDERPATH_D3D10:
1981                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1982                 break;
1983         case RENDERPATH_D3D11:
1984                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1985                 break;
1986         case RENDERPATH_GL20:
1987         case RENDERPATH_GLES2:
1988                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1989                 break;
1990         case RENDERPATH_GL13:
1991         case RENDERPATH_GLES1:
1992                 R_Mesh_TexBind(0, 0);
1993                 R_Mesh_TexBind(1, 0);
1994                 break;
1995         case RENDERPATH_GL11:
1996                 R_Mesh_TexBind(0, 0);
1997                 break;
1998         case RENDERPATH_SOFT:
1999                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2000                 break;
2001         }
2002 }
2003
2004 void R_SetupShader_ShowDepth(qboolean notrippy)
2005 {
2006         int permutation = 0;
2007         if (r_trippy.integer && !notrippy)
2008                 permutation |= SHADERPERMUTATION_TRIPPY;
2009         if (vid.allowalphatocoverage)
2010                 GL_AlphaToCoverage(false);
2011         switch (vid.renderpath)
2012         {
2013         case RENDERPATH_D3D9:
2014 #ifdef SUPPORTHLSL
2015                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2016 #endif
2017                 break;
2018         case RENDERPATH_D3D10:
2019                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2020                 break;
2021         case RENDERPATH_D3D11:
2022                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2023                 break;
2024         case RENDERPATH_GL20:
2025         case RENDERPATH_GLES2:
2026                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2027                 break;
2028         case RENDERPATH_GL13:
2029         case RENDERPATH_GLES1:
2030                 break;
2031         case RENDERPATH_GL11:
2032                 break;
2033         case RENDERPATH_SOFT:
2034                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2035                 break;
2036         }
2037 }
2038
2039 extern qboolean r_shadow_usingdeferredprepass;
2040 extern rtexture_t *r_shadow_attenuationgradienttexture;
2041 extern rtexture_t *r_shadow_attenuation2dtexture;
2042 extern rtexture_t *r_shadow_attenuation3dtexture;
2043 extern qboolean r_shadow_usingshadowmap2d;
2044 extern qboolean r_shadow_usingshadowmaportho;
2045 extern float r_shadow_shadowmap_texturescale[2];
2046 extern float r_shadow_shadowmap_parameters[4];
2047 extern qboolean r_shadow_shadowmapvsdct;
2048 extern qboolean r_shadow_shadowmapsampler;
2049 extern int r_shadow_shadowmappcf;
2050 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2051 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2052 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2053 extern matrix4x4_t r_shadow_shadowmapmatrix;
2054 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2055 extern int r_shadow_prepass_width;
2056 extern int r_shadow_prepass_height;
2057 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2058 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2059 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2060 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2061
2062 #define BLENDFUNC_ALLOWS_COLORMOD      1
2063 #define BLENDFUNC_ALLOWS_FOG           2
2064 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2065 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2066 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2067 static int R_BlendFuncFlags(int src, int dst)
2068 {
2069         int r = 0;
2070
2071         // a blendfunc allows colormod if:
2072         // a) it can never keep the destination pixel invariant, or
2073         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2074         // this is to prevent unintended side effects from colormod
2075
2076         // a blendfunc allows fog if:
2077         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2078         // this is to prevent unintended side effects from fog
2079
2080         // these checks are the output of fogeval.pl
2081
2082         r |= BLENDFUNC_ALLOWS_COLORMOD;
2083         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2084         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2085         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2086         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2087         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2088         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2089         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2090         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2091         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2092         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2093         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2094         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2095         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2096         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2097         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2098         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2099         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2100         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2101         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2102         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2103         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2104
2105         return r;
2106 }
2107
2108 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)
2109 {
2110         // select a permutation of the lighting shader appropriate to this
2111         // combination of texture, entity, light source, and fogging, only use the
2112         // minimum features necessary to avoid wasting rendering time in the
2113         // fragment shader on features that are not being used
2114         unsigned int permutation = 0;
2115         unsigned int mode = 0;
2116         int blendfuncflags;
2117         static float dummy_colormod[3] = {1, 1, 1};
2118         float *colormod = rsurface.colormod;
2119         float m16f[16];
2120         matrix4x4_t tempmatrix;
2121         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2122         if (r_trippy.integer && !notrippy)
2123                 permutation |= SHADERPERMUTATION_TRIPPY;
2124         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2125                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2126         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2127                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2128         if (rsurfacepass == RSURFPASS_BACKGROUND)
2129         {
2130                 // distorted background
2131                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2132                 {
2133                         mode = SHADERMODE_WATER;
2134                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2135                         {
2136                                 // this is the right thing to do for wateralpha
2137                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2138                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2139                         }
2140                         else
2141                         {
2142                                 // this is the right thing to do for entity alpha
2143                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2144                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2145                         }
2146                 }
2147                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2148                 {
2149                         mode = SHADERMODE_REFRACTION;
2150                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2151                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2152                 }
2153                 else
2154                 {
2155                         mode = SHADERMODE_GENERIC;
2156                         permutation |= SHADERPERMUTATION_DIFFUSE;
2157                         GL_BlendFunc(GL_ONE, GL_ZERO);
2158                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2159                 }
2160                 if (vid.allowalphatocoverage)
2161                         GL_AlphaToCoverage(false);
2162         }
2163         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2164         {
2165                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2166                 {
2167                         switch(rsurface.texture->offsetmapping)
2168                         {
2169                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2170                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2171                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2172                         case OFFSETMAPPING_OFF: break;
2173                         }
2174                 }
2175                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2176                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2177                 // normalmap (deferred prepass), may use alpha test on diffuse
2178                 mode = SHADERMODE_DEFERREDGEOMETRY;
2179                 GL_BlendFunc(GL_ONE, GL_ZERO);
2180                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2181                 if (vid.allowalphatocoverage)
2182                         GL_AlphaToCoverage(false);
2183         }
2184         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2185         {
2186                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2187                 {
2188                         switch(rsurface.texture->offsetmapping)
2189                         {
2190                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2191                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2192                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2193                         case OFFSETMAPPING_OFF: break;
2194                         }
2195                 }
2196                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2197                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2198                 // light source
2199                 mode = SHADERMODE_LIGHTSOURCE;
2200                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2201                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2202                 if (diffusescale > 0)
2203                         permutation |= SHADERPERMUTATION_DIFFUSE;
2204                 if (specularscale > 0)
2205                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2206                 if (r_refdef.fogenabled)
2207                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2208                 if (rsurface.texture->colormapping)
2209                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2210                 if (r_shadow_usingshadowmap2d)
2211                 {
2212                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2213                         if(r_shadow_shadowmapvsdct)
2214                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2215
2216                         if (r_shadow_shadowmapsampler)
2217                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2218                         if (r_shadow_shadowmappcf > 1)
2219                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2220                         else if (r_shadow_shadowmappcf)
2221                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2222                         if (r_shadow_shadowmap2ddepthbuffer)
2223                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2224                 }
2225                 if (rsurface.texture->reflectmasktexture)
2226                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2227                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2228                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2229                 if (vid.allowalphatocoverage)
2230                         GL_AlphaToCoverage(false);
2231         }
2232         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2233         {
2234                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2235                 {
2236                         switch(rsurface.texture->offsetmapping)
2237                         {
2238                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2239                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2240                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2241                         case OFFSETMAPPING_OFF: break;
2242                         }
2243                 }
2244                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2245                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2246                 // unshaded geometry (fullbright or ambient model lighting)
2247                 mode = SHADERMODE_FLATCOLOR;
2248                 ambientscale = diffusescale = specularscale = 0;
2249                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2250                         permutation |= SHADERPERMUTATION_GLOW;
2251                 if (r_refdef.fogenabled)
2252                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2253                 if (rsurface.texture->colormapping)
2254                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2255                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2256                 {
2257                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2258                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2259
2260                         if (r_shadow_shadowmapsampler)
2261                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2262                         if (r_shadow_shadowmappcf > 1)
2263                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2264                         else if (r_shadow_shadowmappcf)
2265                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2266                         if (r_shadow_shadowmap2ddepthbuffer)
2267                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2268                 }
2269                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2270                         permutation |= SHADERPERMUTATION_REFLECTION;
2271                 if (rsurface.texture->reflectmasktexture)
2272                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2273                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2274                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2275                 // when using alphatocoverage, we don't need alphakill
2276                 if (vid.allowalphatocoverage)
2277                 {
2278                         if (r_transparent_alphatocoverage.integer)
2279                         {
2280                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2281                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2282                         }
2283                         else
2284                                 GL_AlphaToCoverage(false);
2285                 }
2286         }
2287         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2288         {
2289                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2290                 {
2291                         switch(rsurface.texture->offsetmapping)
2292                         {
2293                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2294                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2295                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2296                         case OFFSETMAPPING_OFF: break;
2297                         }
2298                 }
2299                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2300                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2301                 // directional model lighting
2302                 mode = SHADERMODE_LIGHTDIRECTION;
2303                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2304                         permutation |= SHADERPERMUTATION_GLOW;
2305                 permutation |= SHADERPERMUTATION_DIFFUSE;
2306                 if (specularscale > 0)
2307                         permutation |= SHADERPERMUTATION_SPECULAR;
2308                 if (r_refdef.fogenabled)
2309                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2310                 if (rsurface.texture->colormapping)
2311                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2312                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2313                 {
2314                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2315                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2316
2317                         if (r_shadow_shadowmapsampler)
2318                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2319                         if (r_shadow_shadowmappcf > 1)
2320                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2321                         else if (r_shadow_shadowmappcf)
2322                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2323                         if (r_shadow_shadowmap2ddepthbuffer)
2324                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2325                 }
2326                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2327                         permutation |= SHADERPERMUTATION_REFLECTION;
2328                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2329                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2330                 if (rsurface.texture->reflectmasktexture)
2331                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2332                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2333                 {
2334                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2335                         if (r_shadow_bouncegriddirectional)
2336                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2337                 }
2338                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2339                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2340                 // when using alphatocoverage, we don't need alphakill
2341                 if (vid.allowalphatocoverage)
2342                 {
2343                         if (r_transparent_alphatocoverage.integer)
2344                         {
2345                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2346                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2347                         }
2348                         else
2349                                 GL_AlphaToCoverage(false);
2350                 }
2351         }
2352         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2353         {
2354                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2355                 {
2356                         switch(rsurface.texture->offsetmapping)
2357                         {
2358                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2359                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2360                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2361                         case OFFSETMAPPING_OFF: break;
2362                         }
2363                 }
2364                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2365                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2366                 // ambient model lighting
2367                 mode = SHADERMODE_LIGHTDIRECTION;
2368                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2369                         permutation |= SHADERPERMUTATION_GLOW;
2370                 if (r_refdef.fogenabled)
2371                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2372                 if (rsurface.texture->colormapping)
2373                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2374                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2375                 {
2376                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2377                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2378
2379                         if (r_shadow_shadowmapsampler)
2380                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2381                         if (r_shadow_shadowmappcf > 1)
2382                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2383                         else if (r_shadow_shadowmappcf)
2384                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2385                         if (r_shadow_shadowmap2ddepthbuffer)
2386                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2387                 }
2388                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2389                         permutation |= SHADERPERMUTATION_REFLECTION;
2390                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2391                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2392                 if (rsurface.texture->reflectmasktexture)
2393                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2394                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2395                 {
2396                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2397                         if (r_shadow_bouncegriddirectional)
2398                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2399                 }
2400                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2401                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2402                 // when using alphatocoverage, we don't need alphakill
2403                 if (vid.allowalphatocoverage)
2404                 {
2405                         if (r_transparent_alphatocoverage.integer)
2406                         {
2407                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2408                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2409                         }
2410                         else
2411                                 GL_AlphaToCoverage(false);
2412                 }
2413         }
2414         else
2415         {
2416                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2417                 {
2418                         switch(rsurface.texture->offsetmapping)
2419                         {
2420                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2421                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2422                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2423                         case OFFSETMAPPING_OFF: break;
2424                         }
2425                 }
2426                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2427                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2428                 // lightmapped wall
2429                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2430                         permutation |= SHADERPERMUTATION_GLOW;
2431                 if (r_refdef.fogenabled)
2432                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2433                 if (rsurface.texture->colormapping)
2434                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2435                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2436                 {
2437                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2438                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2439
2440                         if (r_shadow_shadowmapsampler)
2441                                 permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
2442                         if (r_shadow_shadowmappcf > 1)
2443                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
2444                         else if (r_shadow_shadowmappcf)
2445                                 permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
2446                         if (r_shadow_shadowmap2ddepthbuffer)
2447                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2448                 }
2449                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2450                         permutation |= SHADERPERMUTATION_REFLECTION;
2451                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2452                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2453                 if (rsurface.texture->reflectmasktexture)
2454                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2455                 if (FAKELIGHT_ENABLED)
2456                 {
2457                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2458                         mode = SHADERMODE_FAKELIGHT;
2459                         permutation |= SHADERPERMUTATION_DIFFUSE;
2460                         if (specularscale > 0)
2461                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2462                 }
2463                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2464                 {
2465                         // deluxemapping (light direction texture)
2466                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2467                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2468                         else
2469                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2470                         permutation |= SHADERPERMUTATION_DIFFUSE;
2471                         if (specularscale > 0)
2472                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2473                 }
2474                 else if (r_glsl_deluxemapping.integer >= 2)
2475                 {
2476                         // fake deluxemapping (uniform light direction in tangentspace)
2477                         if (rsurface.uselightmaptexture)
2478                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2479                         else
2480                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2481                         permutation |= SHADERPERMUTATION_DIFFUSE;
2482                         if (specularscale > 0)
2483                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2484                 }
2485                 else if (rsurface.uselightmaptexture)
2486                 {
2487                         // ordinary lightmapping (q1bsp, q3bsp)
2488                         mode = SHADERMODE_LIGHTMAP;
2489                 }
2490                 else
2491                 {
2492                         // ordinary vertex coloring (q3bsp)
2493                         mode = SHADERMODE_VERTEXCOLOR;
2494                 }
2495                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2496                 {
2497                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2498                         if (r_shadow_bouncegriddirectional)
2499                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2500                 }
2501                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2502                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2503                 // when using alphatocoverage, we don't need alphakill
2504                 if (vid.allowalphatocoverage)
2505                 {
2506                         if (r_transparent_alphatocoverage.integer)
2507                         {
2508                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2509                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2510                         }
2511                         else
2512                                 GL_AlphaToCoverage(false);
2513                 }
2514         }
2515         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2516                 colormod = dummy_colormod;
2517         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2518                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2519         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2520                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2521         switch(vid.renderpath)
2522         {
2523         case RENDERPATH_D3D9:
2524 #ifdef SUPPORTD3D
2525                 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);
2526                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2527                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2528                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2529                 if (mode == SHADERMODE_LIGHTSOURCE)
2530                 {
2531                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2532                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2533                 }
2534                 else
2535                 {
2536                         if (mode == SHADERMODE_LIGHTDIRECTION)
2537                         {
2538                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2539                         }
2540                 }
2541                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2542                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2543                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2544                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2545                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2546
2547                 if (mode == SHADERMODE_LIGHTSOURCE)
2548                 {
2549                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2550                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2551                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2552                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2553                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2554
2555                         // additive passes are only darkened by fog, not tinted
2556                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2557                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2558                 }
2559                 else
2560                 {
2561                         if (mode == SHADERMODE_FLATCOLOR)
2562                         {
2563                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2564                         }
2565                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2566                         {
2567                                 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]);
2568                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2569                                 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);
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2571                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2573                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2574                         }
2575                         else
2576                         {
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2578                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2581                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2582                         }
2583                         // additive passes are only darkened by fog, not tinted
2584                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2585                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2586                         else
2587                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2588                         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);
2589                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2590                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2591                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2592                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2593                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2594                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2595                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2596                         if (mode == SHADERMODE_WATER)
2597                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2598                 }
2599                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2600                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2601                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2602                 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));
2603                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2604                 if (rsurface.texture->pantstexture)
2605                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2606                 else
2607                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2608                 if (rsurface.texture->shirttexture)
2609                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2610                 else
2611                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2612                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2613                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2614                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2615                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2616                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2617                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2618                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2619                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2620                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2621                         );
2622                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2623                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2624                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2625                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2626
2627                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2628                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2629                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2630                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2631                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2632                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2633                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2634                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2635                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2636                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2637                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2638                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2639                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2640                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2641                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2642                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2643                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2644                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2645                 {
2646                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2647                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2648                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2649                 }
2650                 else
2651                 {
2652                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2653                 }
2654 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2655                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2656                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2657                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2658                 {
2659                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2660                         if (rsurface.rtlight)
2661                         {
2662                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2663                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2664                         }
2665                 }
2666 #endif
2667                 break;
2668         case RENDERPATH_D3D10:
2669                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2670                 break;
2671         case RENDERPATH_D3D11:
2672                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2673                 break;
2674         case RENDERPATH_GL20:
2675         case RENDERPATH_GLES2:
2676                 if (!vid.useinterleavedarrays)
2677                 {
2678                         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);
2679                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2680                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2681                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2682                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2683                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2684                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2685                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2686                 }
2687                 else
2688                 {
2689                         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);
2690                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2691                 }
2692                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2693                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2694                 if (mode == SHADERMODE_LIGHTSOURCE)
2695                 {
2696                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2697                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2698                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2699                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2700                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2701                         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);
2702         
2703                         // additive passes are only darkened by fog, not tinted
2704                         if (r_glsl_permutation->loc_FogColor >= 0)
2705                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2706                         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);
2707                 }
2708                 else
2709                 {
2710                         if (mode == SHADERMODE_FLATCOLOR)
2711                         {
2712                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2713                         }
2714                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2715                         {
2716                                 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]);
2717                                 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]);
2718                                 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);
2719                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2720                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2721                                 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]);
2722                                 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]);
2723                         }
2724                         else
2725                         {
2726                                 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]);
2727                                 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]);
2728                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2729                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2730                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2731                         }
2732                         // additive passes are only darkened by fog, not tinted
2733                         if (r_glsl_permutation->loc_FogColor >= 0)
2734                         {
2735                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2736                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2737                                 else
2738                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2739                         }
2740                         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);
2741                         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]);
2742                         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]);
2743                         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]);
2744                         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]);
2745                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2746                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2747                         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);
2748                         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]);
2749                 }
2750                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2751                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2752                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2753                 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]);
2754                 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]);
2755
2756                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2757                 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));
2758                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2759                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2760                 {
2761                         if (rsurface.texture->pantstexture)
2762                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2763                         else
2764                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2765                 }
2766                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2767                 {
2768                         if (rsurface.texture->shirttexture)
2769                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2770                         else
2771                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2772                 }
2773                 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]);
2774                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2775                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2776                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2777                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2778                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2779                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2780                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2781                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2782                         );
2783                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2784                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2785                 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]);
2786                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2787                 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);}
2788                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2789
2790                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2791                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2792                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2793                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2794                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2795                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2796                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2797                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2798                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2799                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2800                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2801                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2802                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2803                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2804                 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);
2805                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2806                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2807                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2808                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2809                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2810                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2811                 {
2812                         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);
2813                         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);
2814                         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);
2815                 }
2816                 else
2817                 {
2818                         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);
2819                 }
2820                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2821                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2822                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2823                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2824                 {
2825                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2826                         if (rsurface.rtlight)
2827                         {
2828                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2829                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2830                         }
2831                 }
2832                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2833                 CHECKGLERROR
2834                 break;
2835         case RENDERPATH_GL11:
2836         case RENDERPATH_GL13:
2837         case RENDERPATH_GLES1:
2838                 break;
2839         case RENDERPATH_SOFT:
2840                 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);
2841                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2842                 R_SetupShader_SetPermutationSoft(mode, permutation);
2843                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2844                 if (mode == SHADERMODE_LIGHTSOURCE)
2845                 {
2846                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2847                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2848                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2849                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2850                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2851                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2852         
2853                         // additive passes are only darkened by fog, not tinted
2854                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2855                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2856                 }
2857                 else
2858                 {
2859                         if (mode == SHADERMODE_FLATCOLOR)
2860                         {
2861                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2862                         }
2863                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2864                         {
2865                                 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]);
2866                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2867                                 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);
2868                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2869                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2870                                 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]);
2871                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2872                         }
2873                         else
2874                         {
2875                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2879                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2880                         }
2881                         // additive passes are only darkened by fog, not tinted
2882                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2883                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2884                         else
2885                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2886                         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);
2887                         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]);
2888                         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]);
2889                         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]);
2890                         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]);
2891                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2892                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2893                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2894                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2895                 }
2896                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2897                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2898                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2899                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2900                 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]);
2901
2902                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2903                 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));
2904                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2905                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2906                 {
2907                         if (rsurface.texture->pantstexture)
2908                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2909                         else
2910                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2911                 }
2912                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2913                 {
2914                         if (rsurface.texture->shirttexture)
2915                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2916                         else
2917                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2918                 }
2919                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2920                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2921                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2922                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2923                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2924                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2925                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2926                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2927                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2928                         );
2929                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer);
2930                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2931                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2932                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2933
2934                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2935                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2936                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2937                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2938                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2939                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2940                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2941                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2942                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2943                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2944                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2945                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2946                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2947                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2948                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2949                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2950                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2951                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2952                 {
2953                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2954                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2955                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2956                 }
2957                 else
2958                 {
2959                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2960                 }
2961 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2962                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2963                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2964                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2965                 {
2966                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2967                         if (rsurface.rtlight)
2968                         {
2969                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2970                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2971                         }
2972                 }
2973                 break;
2974         }
2975 }
2976
2977 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2978 {
2979         // select a permutation of the lighting shader appropriate to this
2980         // combination of texture, entity, light source, and fogging, only use the
2981         // minimum features necessary to avoid wasting rendering time in the
2982         // fragment shader on features that are not being used
2983         unsigned int permutation = 0;
2984         unsigned int mode = 0;
2985         const float *lightcolorbase = rtlight->currentcolor;
2986         float ambientscale = rtlight->ambientscale;
2987         float diffusescale = rtlight->diffusescale;
2988         float specularscale = rtlight->specularscale;
2989         // this is the location of the light in view space
2990         vec3_t viewlightorigin;
2991         // this transforms from view space (camera) to light space (cubemap)
2992         matrix4x4_t viewtolight;
2993         matrix4x4_t lighttoview;
2994         float viewtolight16f[16];
2995         // light source
2996         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2997         if (rtlight->currentcubemap != r_texture_whitecube)
2998                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2999         if (diffusescale > 0)
3000                 permutation |= SHADERPERMUTATION_DIFFUSE;
3001         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3002                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3003         if (r_shadow_usingshadowmap2d)
3004         {
3005                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3006                 if (r_shadow_shadowmapvsdct)
3007                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3008
3009                 if (r_shadow_shadowmapsampler)
3010                         permutation |= SHADERPERMUTATION_SHADOWSAMPLER;
3011                 if (r_shadow_shadowmappcf > 1)
3012                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF2;
3013                 else if (r_shadow_shadowmappcf)
3014                         permutation |= SHADERPERMUTATION_SHADOWMAPPCF;
3015                 if (r_shadow_shadowmap2ddepthbuffer)
3016                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3017         }
3018         if (vid.allowalphatocoverage)
3019                 GL_AlphaToCoverage(false);
3020         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3021         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3022         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3023         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3024         switch(vid.renderpath)
3025         {
3026         case RENDERPATH_D3D9:
3027 #ifdef SUPPORTD3D
3028                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3029                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3030                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3031                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3032                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3033                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3034                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3035                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3036                 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);
3037                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3038                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3039
3040                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3041                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3042                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3043                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3044                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3045 #endif
3046                 break;
3047         case RENDERPATH_D3D10:
3048                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3049                 break;
3050         case RENDERPATH_D3D11:
3051                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3052                 break;
3053         case RENDERPATH_GL20:
3054         case RENDERPATH_GLES2:
3055                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3056                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3057                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3058                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3059                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3060                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3061                 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]);
3062                 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]);
3063                 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);
3064                 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]);
3065                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3066
3067                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3068                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3069                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3070                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3071                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3072                 break;
3073         case RENDERPATH_GL11:
3074         case RENDERPATH_GL13:
3075         case RENDERPATH_GLES1:
3076                 break;
3077         case RENDERPATH_SOFT:
3078                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3079                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3080                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3081                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3082                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3083                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3084                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3085                 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]);
3086                 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);
3087                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3088                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3089
3090                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3091                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3092                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3093                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3094                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3095                 break;
3096         }
3097 }
3098
3099 #define SKINFRAME_HASH 1024
3100
3101 typedef struct
3102 {
3103         int loadsequence; // incremented each level change
3104         memexpandablearray_t array;
3105         skinframe_t *hash[SKINFRAME_HASH];
3106 }
3107 r_skinframe_t;
3108 r_skinframe_t r_skinframe;
3109
3110 void R_SkinFrame_PrepareForPurge(void)
3111 {
3112         r_skinframe.loadsequence++;
3113         // wrap it without hitting zero
3114         if (r_skinframe.loadsequence >= 200)
3115                 r_skinframe.loadsequence = 1;
3116 }
3117
3118 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3119 {
3120         if (!skinframe)
3121                 return;
3122         // mark the skinframe as used for the purging code
3123         skinframe->loadsequence = r_skinframe.loadsequence;
3124 }
3125
3126 void R_SkinFrame_Purge(void)
3127 {
3128         int i;
3129         skinframe_t *s;
3130         for (i = 0;i < SKINFRAME_HASH;i++)
3131         {
3132                 for (s = r_skinframe.hash[i];s;s = s->next)
3133                 {
3134                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3135                         {
3136                                 if (s->merged == s->base)
3137                                         s->merged = NULL;
3138                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3139                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3140                                 R_PurgeTexture(s->merged);s->merged = NULL;
3141                                 R_PurgeTexture(s->base  );s->base   = NULL;
3142                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3143                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3144                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3145                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3146                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3147                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3148                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3149                                 s->loadsequence = 0;
3150                         }
3151                 }
3152         }
3153 }
3154
3155 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3156         skinframe_t *item;
3157         char basename[MAX_QPATH];
3158
3159         Image_StripImageExtension(name, basename, sizeof(basename));
3160
3161         if( last == NULL ) {
3162                 int hashindex;
3163                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3164                 item = r_skinframe.hash[hashindex];
3165         } else {
3166                 item = last->next;
3167         }
3168
3169         // linearly search through the hash bucket
3170         for( ; item ; item = item->next ) {
3171                 if( !strcmp( item->basename, basename ) ) {
3172                         return item;
3173                 }
3174         }
3175         return NULL;
3176 }
3177
3178 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3179 {
3180         skinframe_t *item;
3181         int hashindex;
3182         char basename[MAX_QPATH];
3183
3184         Image_StripImageExtension(name, basename, sizeof(basename));
3185
3186         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3187         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3188                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3189                         break;
3190
3191         if (!item) {
3192                 rtexture_t *dyntexture;
3193                 // check whether its a dynamic texture
3194                 dyntexture = CL_GetDynTexture( basename );
3195                 if (!add && !dyntexture)
3196                         return NULL;
3197                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3198                 memset(item, 0, sizeof(*item));
3199                 strlcpy(item->basename, basename, sizeof(item->basename));
3200                 item->base = dyntexture; // either NULL or dyntexture handle
3201                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3202                 item->comparewidth = comparewidth;
3203                 item->compareheight = compareheight;
3204                 item->comparecrc = comparecrc;
3205                 item->next = r_skinframe.hash[hashindex];
3206                 r_skinframe.hash[hashindex] = item;
3207         }
3208         else if (textureflags & TEXF_FORCE_RELOAD)
3209         {
3210                 rtexture_t *dyntexture;
3211                 // check whether its a dynamic texture
3212                 dyntexture = CL_GetDynTexture( basename );
3213                 if (!add && !dyntexture)
3214                         return NULL;
3215                 if (item->merged == item->base)
3216                         item->merged = NULL;
3217                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3218                 R_PurgeTexture(item->stain );item->stain  = NULL;
3219                 R_PurgeTexture(item->merged);item->merged = NULL;
3220                 R_PurgeTexture(item->base  );item->base   = NULL;
3221                 R_PurgeTexture(item->pants );item->pants  = NULL;
3222                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3223                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3224                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3225                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3226                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3227         R_PurgeTexture(item->reflect);item->reflect = NULL;
3228                 item->loadsequence = 0;
3229         }
3230         else if( item->base == NULL )
3231         {
3232                 rtexture_t *dyntexture;
3233                 // check whether its a dynamic texture
3234                 // 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]
3235                 dyntexture = CL_GetDynTexture( basename );
3236                 item->base = dyntexture; // either NULL or dyntexture handle
3237         }
3238
3239         R_SkinFrame_MarkUsed(item);
3240         return item;
3241 }
3242
3243 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3244         { \
3245                 unsigned long long avgcolor[5], wsum; \
3246                 int pix, comp, w; \
3247                 avgcolor[0] = 0; \
3248                 avgcolor[1] = 0; \
3249                 avgcolor[2] = 0; \
3250                 avgcolor[3] = 0; \
3251                 avgcolor[4] = 0; \
3252                 wsum = 0; \
3253                 for(pix = 0; pix < cnt; ++pix) \
3254                 { \
3255                         w = 0; \
3256                         for(comp = 0; comp < 3; ++comp) \
3257                                 w += getpixel; \
3258                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3259                         { \
3260                                 ++wsum; \
3261                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3262                                 w = getpixel; \
3263                                 for(comp = 0; comp < 3; ++comp) \
3264                                         avgcolor[comp] += getpixel * w; \
3265                                 avgcolor[3] += w; \
3266                         } \
3267                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3268                         avgcolor[4] += getpixel; \
3269                 } \
3270                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3271                         avgcolor[3] = 1; \
3272                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3273                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3274                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3275                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3276         }
3277
3278 extern cvar_t gl_picmip;
3279 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3280 {
3281         int j;
3282         unsigned char *pixels;
3283         unsigned char *bumppixels;
3284         unsigned char *basepixels = NULL;
3285         int basepixels_width = 0;
3286         int basepixels_height = 0;
3287         skinframe_t *skinframe;
3288         rtexture_t *ddsbase = NULL;
3289         qboolean ddshasalpha = false;
3290         float ddsavgcolor[4];
3291         char basename[MAX_QPATH];
3292         int miplevel = R_PicmipForFlags(textureflags);
3293         int savemiplevel = miplevel;
3294         int mymiplevel;
3295         char vabuf[1024];
3296
3297         if (cls.state == ca_dedicated)
3298                 return NULL;
3299
3300         // return an existing skinframe if already loaded
3301         // if loading of the first image fails, don't make a new skinframe as it
3302         // would cause all future lookups of this to be missing
3303         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3304         if (skinframe && skinframe->base)
3305                 return skinframe;
3306
3307         Image_StripImageExtension(name, basename, sizeof(basename));
3308
3309         // check for DDS texture file first
3310         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3311         {
3312                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3313                 if (basepixels == NULL)
3314                         return NULL;
3315         }
3316
3317         // FIXME handle miplevel
3318
3319         if (developer_loading.integer)
3320                 Con_Printf("loading skin \"%s\"\n", name);
3321
3322         // we've got some pixels to store, so really allocate this new texture now
3323         if (!skinframe)
3324                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3325         textureflags &= ~TEXF_FORCE_RELOAD;
3326         skinframe->stain = NULL;
3327         skinframe->merged = NULL;
3328         skinframe->base = NULL;
3329         skinframe->pants = NULL;
3330         skinframe->shirt = NULL;
3331         skinframe->nmap = NULL;
3332         skinframe->gloss = NULL;
3333         skinframe->glow = NULL;
3334         skinframe->fog = NULL;
3335         skinframe->reflect = NULL;
3336         skinframe->hasalpha = false;
3337
3338         if (ddsbase)
3339         {
3340                 skinframe->base = ddsbase;
3341                 skinframe->hasalpha = ddshasalpha;
3342                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3343                 if (r_loadfog && skinframe->hasalpha)
3344                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3345                 //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]);
3346         }
3347         else
3348         {
3349                 basepixels_width = image_width;
3350                 basepixels_height = image_height;
3351                 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);
3352                 if (textureflags & TEXF_ALPHA)
3353                 {
3354                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3355                         {
3356                                 if (basepixels[j] < 255)
3357                                 {
3358                                         skinframe->hasalpha = true;
3359                                         break;
3360                                 }
3361                         }
3362                         if (r_loadfog && skinframe->hasalpha)
3363                         {
3364                                 // has transparent pixels
3365                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3366                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3367                                 {
3368                                         pixels[j+0] = 255;
3369                                         pixels[j+1] = 255;
3370                                         pixels[j+2] = 255;
3371                                         pixels[j+3] = basepixels[j+3];
3372                                 }
3373                                 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);
3374                                 Mem_Free(pixels);
3375                         }
3376                 }
3377                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3378 #ifndef USE_GLES2
3379                 //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]);
3380                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3381                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3382                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3383                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3384 #endif
3385         }
3386
3387         if (r_loaddds)
3388         {
3389                 mymiplevel = savemiplevel;
3390                 if (r_loadnormalmap)
3391                         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);
3392                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3393                 if (r_loadgloss)
3394                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3395                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3396                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3397                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3398         }
3399
3400         // _norm is the name used by tenebrae and has been adopted as standard
3401         if (r_loadnormalmap && skinframe->nmap == NULL)
3402         {
3403                 mymiplevel = savemiplevel;
3404                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3405                 {
3406                         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);
3407                         Mem_Free(pixels);
3408                         pixels = NULL;
3409                 }
3410                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3411                 {
3412                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3413                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3414                         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);
3415                         Mem_Free(pixels);
3416                         Mem_Free(bumppixels);
3417                 }
3418                 else if (r_shadow_bumpscale_basetexture.value > 0)
3419                 {
3420                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3421                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3422                         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);
3423                         Mem_Free(pixels);
3424                 }
3425 #ifndef USE_GLES2
3426                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3427                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3428 #endif
3429         }
3430
3431         // _luma is supported only for tenebrae compatibility
3432         // _glow is the preferred name
3433         mymiplevel = savemiplevel;
3434         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))))
3435         {
3436                 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);
3437 #ifndef USE_GLES2
3438                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3439                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3440 #endif
3441                 Mem_Free(pixels);pixels = NULL;
3442         }
3443
3444         mymiplevel = savemiplevel;
3445         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3446         {
3447                 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);
3448 #ifndef USE_GLES2
3449                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3450                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3451 #endif
3452                 Mem_Free(pixels);
3453                 pixels = NULL;
3454         }
3455
3456         mymiplevel = savemiplevel;
3457         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3458         {
3459                 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);
3460 #ifndef USE_GLES2
3461                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3462                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3463 #endif
3464                 Mem_Free(pixels);
3465                 pixels = NULL;
3466         }
3467
3468         mymiplevel = savemiplevel;
3469         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3470         {
3471                 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);
3472 #ifndef USE_GLES2
3473                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3474                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3475 #endif
3476                 Mem_Free(pixels);
3477                 pixels = NULL;
3478         }
3479
3480         mymiplevel = savemiplevel;
3481         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3482         {
3483                 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);
3484 #ifndef USE_GLES2
3485                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3486                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3487 #endif
3488                 Mem_Free(pixels);
3489                 pixels = NULL;
3490         }
3491
3492         if (basepixels)
3493                 Mem_Free(basepixels);
3494
3495         return skinframe;
3496 }
3497
3498 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3499 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3500 {
3501         int i;
3502         unsigned char *temp1, *temp2;
3503         skinframe_t *skinframe;
3504         char vabuf[1024];
3505
3506         if (cls.state == ca_dedicated)
3507                 return NULL;
3508
3509         // if already loaded just return it, otherwise make a new skinframe
3510         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3511         if (skinframe && skinframe->base)
3512                 return skinframe;
3513         textureflags &= ~TEXF_FORCE_RELOAD;
3514
3515         skinframe->stain = NULL;
3516         skinframe->merged = NULL;
3517         skinframe->base = NULL;
3518         skinframe->pants = NULL;
3519         skinframe->shirt = NULL;
3520         skinframe->nmap = NULL;
3521         skinframe->gloss = NULL;
3522         skinframe->glow = NULL;
3523         skinframe->fog = NULL;
3524         skinframe->reflect = NULL;
3525         skinframe->hasalpha = false;
3526
3527         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3528         if (!skindata)
3529                 return NULL;
3530
3531         if (developer_loading.integer)
3532                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3533
3534         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3535         {
3536                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3537                 temp2 = temp1 + width * height * 4;
3538                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3539                 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);
3540                 Mem_Free(temp1);
3541         }
3542         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3543         if (textureflags & TEXF_ALPHA)
3544         {
3545                 for (i = 3;i < width * height * 4;i += 4)
3546                 {
3547                         if (skindata[i] < 255)
3548                         {
3549                                 skinframe->hasalpha = true;
3550                                 break;
3551                         }
3552                 }
3553                 if (r_loadfog && skinframe->hasalpha)
3554                 {
3555                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3556                         memcpy(fogpixels, skindata, width * height * 4);
3557                         for (i = 0;i < width * height * 4;i += 4)
3558                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3559                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3560                         Mem_Free(fogpixels);
3561                 }
3562         }
3563
3564         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3565         //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]);
3566
3567         return skinframe;
3568 }
3569
3570 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3571 {
3572         int i;
3573         int featuresmask;
3574         skinframe_t *skinframe;
3575
3576         if (cls.state == ca_dedicated)
3577                 return NULL;
3578
3579         // if already loaded just return it, otherwise make a new skinframe
3580         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3581         if (skinframe && skinframe->base)
3582                 return skinframe;
3583         textureflags &= ~TEXF_FORCE_RELOAD;
3584
3585         skinframe->stain = NULL;
3586         skinframe->merged = NULL;
3587         skinframe->base = NULL;
3588         skinframe->pants = NULL;
3589         skinframe->shirt = NULL;
3590         skinframe->nmap = NULL;
3591         skinframe->gloss = NULL;
3592         skinframe->glow = NULL;
3593         skinframe->fog = NULL;
3594         skinframe->reflect = NULL;
3595         skinframe->hasalpha = false;
3596
3597         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3598         if (!skindata)
3599                 return NULL;
3600
3601         if (developer_loading.integer)
3602                 Con_Printf("loading quake skin \"%s\"\n", name);
3603
3604         // 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)
3605         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3606         memcpy(skinframe->qpixels, skindata, width*height);
3607         skinframe->qwidth = width;
3608         skinframe->qheight = height;
3609
3610         featuresmask = 0;
3611         for (i = 0;i < width * height;i++)
3612                 featuresmask |= palette_featureflags[skindata[i]];
3613
3614         skinframe->hasalpha = false;
3615         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3616         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3617         skinframe->qgeneratemerged = true;
3618         skinframe->qgeneratebase = skinframe->qhascolormapping;
3619         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3620
3621         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3622         //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]);
3623
3624         return skinframe;
3625 }
3626
3627 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3628 {
3629         int width;
3630         int height;
3631         unsigned char *skindata;
3632         char vabuf[1024];
3633
3634         if (!skinframe->qpixels)
3635                 return;
3636
3637         if (!skinframe->qhascolormapping)
3638                 colormapped = false;
3639
3640         if (colormapped)
3641         {
3642                 if (!skinframe->qgeneratebase)
3643                         return;
3644         }
3645         else
3646         {
3647                 if (!skinframe->qgeneratemerged)
3648                         return;
3649         }
3650
3651         width = skinframe->qwidth;
3652         height = skinframe->qheight;
3653         skindata = skinframe->qpixels;
3654
3655         if (skinframe->qgeneratenmap)
3656         {
3657                 unsigned char *temp1, *temp2;
3658                 skinframe->qgeneratenmap = false;
3659                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3660                 temp2 = temp1 + width * height * 4;
3661                 // use either a custom palette or the quake palette
3662                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3663                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3664                 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);
3665                 Mem_Free(temp1);
3666         }
3667
3668         if (skinframe->qgenerateglow)
3669         {
3670                 skinframe->qgenerateglow = false;
3671                 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
3672         }
3673
3674         if (colormapped)
3675         {
3676                 skinframe->qgeneratebase = false;
3677                 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);
3678                 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);
3679                 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);
3680         }
3681         else
3682         {
3683                 skinframe->qgeneratemerged = false;
3684                 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);
3685         }
3686
3687         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3688         {
3689                 Mem_Free(skinframe->qpixels);
3690                 skinframe->qpixels = NULL;
3691         }
3692 }
3693
3694 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)
3695 {
3696         int i;
3697         skinframe_t *skinframe;
3698         char vabuf[1024];
3699
3700         if (cls.state == ca_dedicated)
3701                 return NULL;
3702
3703         // if already loaded just return it, otherwise make a new skinframe
3704         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3705         if (skinframe && skinframe->base)
3706                 return skinframe;
3707         textureflags &= ~TEXF_FORCE_RELOAD;
3708
3709         skinframe->stain = NULL;
3710         skinframe->merged = NULL;
3711         skinframe->base = NULL;
3712         skinframe->pants = NULL;
3713         skinframe->shirt = NULL;
3714         skinframe->nmap = NULL;
3715         skinframe->gloss = NULL;
3716         skinframe->glow = NULL;
3717         skinframe->fog = NULL;
3718         skinframe->reflect = NULL;
3719         skinframe->hasalpha = false;
3720
3721         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3722         if (!skindata)
3723                 return NULL;
3724
3725         if (developer_loading.integer)
3726                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3727
3728         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3729         if (textureflags & TEXF_ALPHA)
3730         {
3731                 for (i = 0;i < width * height;i++)
3732                 {
3733                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3734                         {
3735                                 skinframe->hasalpha = true;
3736                                 break;
3737                         }
3738                 }
3739                 if (r_loadfog && skinframe->hasalpha)
3740                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3741         }
3742
3743         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3744         //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]);
3745
3746         return skinframe;
3747 }
3748
3749 skinframe_t *R_SkinFrame_LoadMissing(void)
3750 {
3751         skinframe_t *skinframe;
3752
3753         if (cls.state == ca_dedicated)
3754                 return NULL;
3755
3756         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3757         skinframe->stain = NULL;
3758         skinframe->merged = NULL;
3759         skinframe->base = NULL;
3760         skinframe->pants = NULL;
3761         skinframe->shirt = NULL;
3762         skinframe->nmap = NULL;
3763         skinframe->gloss = NULL;
3764         skinframe->glow = NULL;
3765         skinframe->fog = NULL;
3766         skinframe->reflect = NULL;
3767         skinframe->hasalpha = false;
3768
3769         skinframe->avgcolor[0] = rand() / RAND_MAX;
3770         skinframe->avgcolor[1] = rand() / RAND_MAX;
3771         skinframe->avgcolor[2] = rand() / RAND_MAX;
3772         skinframe->avgcolor[3] = 1;
3773
3774         return skinframe;
3775 }
3776
3777 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3778 typedef struct suffixinfo_s
3779 {
3780         const char *suffix;
3781         qboolean flipx, flipy, flipdiagonal;
3782 }
3783 suffixinfo_t;
3784 static suffixinfo_t suffix[3][6] =
3785 {
3786         {
3787                 {"px",   false, false, false},
3788                 {"nx",   false, false, false},
3789                 {"py",   false, false, false},
3790                 {"ny",   false, false, false},
3791                 {"pz",   false, false, false},
3792                 {"nz",   false, false, false}
3793         },
3794         {
3795                 {"posx", false, false, false},
3796                 {"negx", false, false, false},
3797                 {"posy", false, false, false},
3798                 {"negy", false, false, false},
3799                 {"posz", false, false, false},
3800                 {"negz", false, false, false}
3801         },
3802         {
3803                 {"rt",    true, false,  true},
3804                 {"lf",   false,  true,  true},
3805                 {"ft",    true,  true, false},
3806                 {"bk",   false, false, false},
3807                 {"up",    true, false,  true},
3808                 {"dn",    true, false,  true}
3809         }
3810 };
3811
3812 static int componentorder[4] = {0, 1, 2, 3};
3813
3814 static rtexture_t *R_LoadCubemap(const char *basename)
3815 {
3816         int i, j, cubemapsize;
3817         unsigned char *cubemappixels, *image_buffer;
3818         rtexture_t *cubemaptexture;
3819         char name[256];
3820         // must start 0 so the first loadimagepixels has no requested width/height
3821         cubemapsize = 0;
3822         cubemappixels = NULL;
3823         cubemaptexture = NULL;
3824         // keep trying different suffix groups (posx, px, rt) until one loads
3825         for (j = 0;j < 3 && !cubemappixels;j++)
3826         {
3827                 // load the 6 images in the suffix group
3828                 for (i = 0;i < 6;i++)
3829                 {
3830                         // generate an image name based on the base and and suffix
3831                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3832                         // load it
3833                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3834                         {
3835                                 // an image loaded, make sure width and height are equal
3836                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3837                                 {
3838                                         // if this is the first image to load successfully, allocate the cubemap memory
3839                                         if (!cubemappixels && image_width >= 1)
3840                                         {
3841                                                 cubemapsize = image_width;
3842                                                 // note this clears to black, so unavailable sides are black
3843                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3844                                         }
3845                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3846                                         if (cubemappixels)
3847                                                 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);
3848                                 }
3849                                 else
3850                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3851                                 // free the image
3852                                 Mem_Free(image_buffer);
3853                         }
3854                 }
3855         }
3856         // if a cubemap loaded, upload it
3857         if (cubemappixels)
3858         {
3859                 if (developer_loading.integer)
3860                         Con_Printf("loading cubemap \"%s\"\n", basename);
3861
3862                 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);
3863                 Mem_Free(cubemappixels);
3864         }
3865         else
3866         {
3867                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3868                 if (developer_loading.integer)
3869                 {
3870                         Con_Printf("(tried tried images ");
3871                         for (j = 0;j < 3;j++)
3872                                 for (i = 0;i < 6;i++)
3873                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3874                         Con_Print(" and was unable to find any of them).\n");
3875                 }
3876         }
3877         return cubemaptexture;
3878 }
3879
3880 rtexture_t *R_GetCubemap(const char *basename)
3881 {
3882         int i;
3883         for (i = 0;i < r_texture_numcubemaps;i++)
3884                 if (r_texture_cubemaps[i] != NULL)
3885                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3886                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3887         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3888                 return r_texture_whitecube;
3889         r_texture_numcubemaps++;
3890         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3891         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3892         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3893         return r_texture_cubemaps[i]->texture;
3894 }
3895
3896 static void R_Main_FreeViewCache(void)
3897 {
3898         if (r_refdef.viewcache.entityvisible)
3899                 Mem_Free(r_refdef.viewcache.entityvisible);
3900         if (r_refdef.viewcache.world_pvsbits)
3901                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3902         if (r_refdef.viewcache.world_leafvisible)
3903                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3904         if (r_refdef.viewcache.world_surfacevisible)
3905                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3906         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3907 }
3908
3909 static void R_Main_ResizeViewCache(void)
3910 {
3911         int numentities = r_refdef.scene.numentities;
3912         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3913         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3914         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3915         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3916         if (r_refdef.viewcache.maxentities < numentities)
3917         {
3918                 r_refdef.viewcache.maxentities = numentities;
3919                 if (r_refdef.viewcache.entityvisible)
3920                         Mem_Free(r_refdef.viewcache.entityvisible);
3921                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3922         }
3923         if (r_refdef.viewcache.world_numclusters != numclusters)
3924         {
3925                 r_refdef.viewcache.world_numclusters = numclusters;
3926                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3927                 if (r_refdef.viewcache.world_pvsbits)
3928                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3929                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3930         }
3931         if (r_refdef.viewcache.world_numleafs != numleafs)
3932         {
3933                 r_refdef.viewcache.world_numleafs = numleafs;
3934                 if (r_refdef.viewcache.world_leafvisible)
3935                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3936                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3937         }
3938         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3939         {
3940                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3941                 if (r_refdef.viewcache.world_surfacevisible)
3942                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3943                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3944         }
3945 }
3946
3947 extern rtexture_t *loadingscreentexture;
3948 static void gl_main_start(void)
3949 {
3950         loadingscreentexture = NULL;
3951         r_texture_blanknormalmap = NULL;
3952         r_texture_white = NULL;
3953         r_texture_grey128 = NULL;
3954         r_texture_black = NULL;
3955         r_texture_whitecube = NULL;
3956         r_texture_normalizationcube = NULL;
3957         r_texture_fogattenuation = NULL;
3958         r_texture_fogheighttexture = NULL;
3959         r_texture_gammaramps = NULL;
3960         r_texture_numcubemaps = 0;
3961
3962         r_loaddds = r_texture_dds_load.integer != 0;
3963         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3964
3965         switch(vid.renderpath)
3966         {
3967         case RENDERPATH_GL20:
3968         case RENDERPATH_D3D9:
3969         case RENDERPATH_D3D10:
3970         case RENDERPATH_D3D11:
3971         case RENDERPATH_SOFT:
3972         case RENDERPATH_GLES2:
3973                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3974                 Cvar_SetValueQuick(&gl_combine, 1);
3975                 Cvar_SetValueQuick(&r_glsl, 1);
3976                 r_loadnormalmap = true;
3977                 r_loadgloss = true;
3978                 r_loadfog = false;
3979                 break;
3980         case RENDERPATH_GL13:
3981         case RENDERPATH_GLES1:
3982                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3983                 Cvar_SetValueQuick(&gl_combine, 1);
3984                 Cvar_SetValueQuick(&r_glsl, 0);
3985                 r_loadnormalmap = false;
3986                 r_loadgloss = false;
3987                 r_loadfog = true;
3988                 break;
3989         case RENDERPATH_GL11:
3990                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3991                 Cvar_SetValueQuick(&gl_combine, 0);
3992                 Cvar_SetValueQuick(&r_glsl, 0);
3993                 r_loadnormalmap = false;
3994                 r_loadgloss = false;
3995                 r_loadfog = true;
3996                 break;
3997         }
3998
3999         R_AnimCache_Free();
4000         R_FrameData_Reset();
4001
4002         r_numqueries = 0;
4003         r_maxqueries = 0;
4004         memset(r_queries, 0, sizeof(r_queries));
4005
4006         r_qwskincache = NULL;
4007         r_qwskincache_size = 0;
4008
4009         // due to caching of texture_t references, the collision cache must be reset
4010         Collision_Cache_Reset(true);
4011
4012         // set up r_skinframe loading system for textures
4013         memset(&r_skinframe, 0, sizeof(r_skinframe));
4014         r_skinframe.loadsequence = 1;
4015         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4016
4017         r_main_texturepool = R_AllocTexturePool();
4018         R_BuildBlankTextures();
4019         R_BuildNoTexture();
4020         if (vid.support.arb_texture_cube_map)
4021         {
4022                 R_BuildWhiteCube();
4023                 R_BuildNormalizationCube();
4024         }
4025         r_texture_fogattenuation = NULL;
4026         r_texture_fogheighttexture = NULL;
4027         r_texture_gammaramps = NULL;
4028         //r_texture_fogintensity = NULL;
4029         memset(&r_fb, 0, sizeof(r_fb));
4030         r_glsl_permutation = NULL;
4031         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4032         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4033         glslshaderstring = NULL;
4034 #ifdef SUPPORTD3D
4035         r_hlsl_permutation = NULL;
4036         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4037         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4038 #endif
4039         hlslshaderstring = NULL;
4040         memset(&r_svbsp, 0, sizeof (r_svbsp));
4041
4042         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4043         r_texture_numcubemaps = 0;
4044
4045         r_refdef.fogmasktable_density = 0;
4046 }
4047
4048 static void gl_main_shutdown(void)
4049 {
4050         R_AnimCache_Free();
4051         R_FrameData_Reset();
4052
4053         R_Main_FreeViewCache();
4054
4055         switch(vid.renderpath)
4056         {
4057         case RENDERPATH_GL11:
4058         case RENDERPATH_GL13:
4059         case RENDERPATH_GL20:
4060         case RENDERPATH_GLES1:
4061         case RENDERPATH_GLES2:
4062 #ifdef GL_SAMPLES_PASSED_ARB
4063                 if (r_maxqueries)
4064                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4065 #endif
4066                 break;
4067         case RENDERPATH_D3D9:
4068                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4069                 break;
4070         case RENDERPATH_D3D10:
4071                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4072                 break;
4073         case RENDERPATH_D3D11:
4074                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4075                 break;
4076         case RENDERPATH_SOFT:
4077                 break;
4078         }
4079
4080         r_numqueries = 0;
4081         r_maxqueries = 0;
4082         memset(r_queries, 0, sizeof(r_queries));
4083
4084         r_qwskincache = NULL;
4085         r_qwskincache_size = 0;
4086
4087         // clear out the r_skinframe state
4088         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4089         memset(&r_skinframe, 0, sizeof(r_skinframe));
4090
4091         if (r_svbsp.nodes)
4092                 Mem_Free(r_svbsp.nodes);
4093         memset(&r_svbsp, 0, sizeof (r_svbsp));
4094         R_FreeTexturePool(&r_main_texturepool);
4095         loadingscreentexture = NULL;
4096         r_texture_blanknormalmap = NULL;
4097         r_texture_white = NULL;
4098         r_texture_grey128 = NULL;
4099         r_texture_black = NULL;
4100         r_texture_whitecube = NULL;
4101         r_texture_normalizationcube = NULL;
4102         r_texture_fogattenuation = NULL;
4103         r_texture_fogheighttexture = NULL;
4104         r_texture_gammaramps = NULL;
4105         r_texture_numcubemaps = 0;
4106         //r_texture_fogintensity = NULL;
4107         memset(&r_fb, 0, sizeof(r_fb));
4108         R_GLSL_Restart_f();
4109
4110         r_glsl_permutation = NULL;
4111         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4112         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4113         glslshaderstring = NULL;
4114 #ifdef SUPPORTD3D
4115         r_hlsl_permutation = NULL;
4116         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4117         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4118 #endif
4119         hlslshaderstring = NULL;
4120 }
4121
4122 static void gl_main_newmap(void)
4123 {
4124         // FIXME: move this code to client
4125         char *entities, entname[MAX_QPATH];
4126         if (r_qwskincache)
4127                 Mem_Free(r_qwskincache);
4128         r_qwskincache = NULL;
4129         r_qwskincache_size = 0;
4130         if (cl.worldmodel)
4131         {
4132                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4133                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4134                 {
4135                         CL_ParseEntityLump(entities);
4136                         Mem_Free(entities);
4137                         return;
4138                 }
4139                 if (cl.worldmodel->brush.entities)
4140                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4141         }
4142         R_Main_FreeViewCache();
4143
4144         R_FrameData_Reset();
4145 }
4146
4147 void GL_Main_Init(void)
4148 {
4149         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4150
4151         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4152         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4153         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4154         if (gamemode == GAME_NEHAHRA)
4155         {
4156                 Cvar_RegisterVariable (&gl_fogenable);
4157                 Cvar_RegisterVariable (&gl_fogdensity);
4158                 Cvar_RegisterVariable (&gl_fogred);
4159                 Cvar_RegisterVariable (&gl_foggreen);
4160                 Cvar_RegisterVariable (&gl_fogblue);
4161                 Cvar_RegisterVariable (&gl_fogstart);
4162                 Cvar_RegisterVariable (&gl_fogend);
4163                 Cvar_RegisterVariable (&gl_skyclip);
4164         }
4165         Cvar_RegisterVariable(&r_motionblur);
4166         Cvar_RegisterVariable(&r_damageblur);
4167         Cvar_RegisterVariable(&r_motionblur_averaging);
4168         Cvar_RegisterVariable(&r_motionblur_randomize);
4169         Cvar_RegisterVariable(&r_motionblur_minblur);
4170         Cvar_RegisterVariable(&r_motionblur_maxblur);
4171         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4172         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4173         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4174         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4175         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4176         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4177         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4178         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4179         Cvar_RegisterVariable(&r_equalize_entities_by);
4180         Cvar_RegisterVariable(&r_equalize_entities_to);
4181         Cvar_RegisterVariable(&r_depthfirst);
4182         Cvar_RegisterVariable(&r_useinfinitefarclip);
4183         Cvar_RegisterVariable(&r_farclip_base);
4184         Cvar_RegisterVariable(&r_farclip_world);
4185         Cvar_RegisterVariable(&r_nearclip);
4186         Cvar_RegisterVariable(&r_deformvertexes);
4187         Cvar_RegisterVariable(&r_transparent);
4188         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4189         Cvar_RegisterVariable(&r_showoverdraw);
4190         Cvar_RegisterVariable(&r_showbboxes);
4191         Cvar_RegisterVariable(&r_showsurfaces);
4192         Cvar_RegisterVariable(&r_showtris);
4193         Cvar_RegisterVariable(&r_shownormals);
4194         Cvar_RegisterVariable(&r_showlighting);
4195         Cvar_RegisterVariable(&r_showshadowvolumes);
4196         Cvar_RegisterVariable(&r_showcollisionbrushes);
4197         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4198         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4199         Cvar_RegisterVariable(&r_showdisabledepthtest);
4200         Cvar_RegisterVariable(&r_drawportals);
4201         Cvar_RegisterVariable(&r_drawentities);
4202         Cvar_RegisterVariable(&r_draw2d);
4203         Cvar_RegisterVariable(&r_drawworld);
4204         Cvar_RegisterVariable(&r_cullentities_trace);
4205         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4206         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4207         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4208         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4209         Cvar_RegisterVariable(&r_sortentities);
4210         Cvar_RegisterVariable(&r_drawviewmodel);
4211         Cvar_RegisterVariable(&r_drawexteriormodel);
4212         Cvar_RegisterVariable(&r_speeds);
4213         Cvar_RegisterVariable(&r_fullbrights);
4214         Cvar_RegisterVariable(&r_wateralpha);
4215         Cvar_RegisterVariable(&r_dynamic);
4216         Cvar_RegisterVariable(&r_fakelight);
4217         Cvar_RegisterVariable(&r_fakelight_intensity);
4218         Cvar_RegisterVariable(&r_fullbright);
4219         Cvar_RegisterVariable(&r_shadows);
4220         Cvar_RegisterVariable(&r_shadows_darken);
4221         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4222         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4223         Cvar_RegisterVariable(&r_shadows_throwdistance);
4224         Cvar_RegisterVariable(&r_shadows_throwdirection);
4225         Cvar_RegisterVariable(&r_shadows_focus);
4226         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4227         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4228         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4229         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4230         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4231         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4232         Cvar_RegisterVariable(&r_fog_exp2);
4233         Cvar_RegisterVariable(&r_fog_clear);
4234         Cvar_RegisterVariable(&r_drawfog);
4235         Cvar_RegisterVariable(&r_transparentdepthmasking);
4236         Cvar_RegisterVariable(&r_transparent_sortmindist);
4237         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4238         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4239         Cvar_RegisterVariable(&r_texture_dds_load);
4240         Cvar_RegisterVariable(&r_texture_dds_save);
4241         Cvar_RegisterVariable(&r_textureunits);
4242         Cvar_RegisterVariable(&gl_combine);
4243         Cvar_RegisterVariable(&r_usedepthtextures);
4244         Cvar_RegisterVariable(&r_viewfbo);
4245         Cvar_RegisterVariable(&r_viewscale);
4246         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4247         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4248         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4249         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4250         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4251         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4252         Cvar_RegisterVariable(&r_glsl);
4253         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4254         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4255         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4256         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4257         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4258         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4259         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4260         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4261         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4262         Cvar_RegisterVariable(&r_glsl_postprocess);
4263         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4264         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4265         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4266         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4267         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4268         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4269         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4270         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4271
4272         Cvar_RegisterVariable(&r_water);
4273         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4274         Cvar_RegisterVariable(&r_water_clippingplanebias);
4275         Cvar_RegisterVariable(&r_water_refractdistort);
4276         Cvar_RegisterVariable(&r_water_reflectdistort);
4277         Cvar_RegisterVariable(&r_water_scissormode);
4278         Cvar_RegisterVariable(&r_water_lowquality);
4279         Cvar_RegisterVariable(&r_water_hideplayer);
4280         Cvar_RegisterVariable(&r_water_fbo);
4281
4282         Cvar_RegisterVariable(&r_lerpsprites);
4283         Cvar_RegisterVariable(&r_lerpmodels);
4284         Cvar_RegisterVariable(&r_lerplightstyles);
4285         Cvar_RegisterVariable(&r_waterscroll);
4286         Cvar_RegisterVariable(&r_bloom);
4287         Cvar_RegisterVariable(&r_bloom_colorscale);
4288         Cvar_RegisterVariable(&r_bloom_brighten);
4289         Cvar_RegisterVariable(&r_bloom_blur);
4290         Cvar_RegisterVariable(&r_bloom_resolution);
4291         Cvar_RegisterVariable(&r_bloom_colorexponent);
4292         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4293         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4294         Cvar_RegisterVariable(&r_hdr_glowintensity);
4295         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4296         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4297         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4298         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4299         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4300         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4301         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4302         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4303         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4304         Cvar_RegisterVariable(&developer_texturelogging);
4305         Cvar_RegisterVariable(&gl_lightmaps);
4306         Cvar_RegisterVariable(&r_test);
4307         Cvar_RegisterVariable(&r_glsl_saturation);
4308         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4309         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4310         Cvar_RegisterVariable(&r_framedatasize);
4311         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4312                 Cvar_SetValue("r_fullbrights", 0);
4313         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4314 }
4315
4316 void Render_Init(void)
4317 {
4318         gl_backend_init();
4319         R_Textures_Init();
4320         GL_Main_Init();
4321         Font_Init();
4322         GL_Draw_Init();
4323         R_Shadow_Init();
4324         R_Sky_Init();
4325         GL_Surf_Init();
4326         Sbar_Init();
4327         R_Particles_Init();
4328         R_Explosion_Init();
4329         R_LightningBeams_Init();
4330         Mod_RenderInit();
4331 }
4332
4333 /*
4334 ===============
4335 GL_Init
4336 ===============
4337 */
4338 #ifndef USE_GLES2
4339 extern char *ENGINE_EXTENSIONS;
4340 void GL_Init (void)
4341 {
4342         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4343         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4344         gl_version = (const char *)qglGetString(GL_VERSION);
4345         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4346
4347         if (!gl_extensions)
4348                 gl_extensions = "";
4349         if (!gl_platformextensions)
4350                 gl_platformextensions = "";
4351
4352         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4353         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4354         Con_Printf("GL_VERSION: %s\n", gl_version);
4355         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4356         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4357
4358         VID_CheckExtensions();
4359
4360         // LordHavoc: report supported extensions
4361         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4362
4363         // clear to black (loading plaque will be seen over this)
4364         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4365 }
4366 #endif
4367
4368 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4369 {
4370         int i;
4371         mplane_t *p;
4372         if (r_trippy.integer)
4373                 return false;
4374         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4375         {
4376                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4377                 if (i == 4)
4378                         continue;
4379                 p = r_refdef.view.frustum + i;
4380                 switch(p->signbits)
4381                 {
4382                 default:
4383                 case 0:
4384                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4385                                 return true;
4386                         break;
4387                 case 1:
4388                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4389                                 return true;
4390                         break;
4391                 case 2:
4392                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4393                                 return true;
4394                         break;
4395                 case 3:
4396                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4397                                 return true;
4398                         break;
4399                 case 4:
4400                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4401                                 return true;
4402                         break;
4403                 case 5:
4404                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4405                                 return true;
4406                         break;
4407                 case 6:
4408                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4409                                 return true;
4410                         break;
4411                 case 7:
4412                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4413                                 return true;
4414                         break;
4415                 }
4416         }
4417         return false;
4418 }
4419
4420 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4421 {
4422         int i;
4423         const mplane_t *p;
4424         if (r_trippy.integer)
4425                 return false;
4426         for (i = 0;i < numplanes;i++)
4427         {
4428                 p = planes + i;
4429                 switch(p->signbits)
4430                 {
4431                 default:
4432                 case 0:
4433                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4434                                 return true;
4435                         break;
4436                 case 1:
4437                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4438                                 return true;
4439                         break;
4440                 case 2:
4441                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4442                                 return true;
4443                         break;
4444                 case 3:
4445                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4446                                 return true;
4447                         break;
4448                 case 4:
4449                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4450                                 return true;
4451                         break;
4452                 case 5:
4453                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4454                                 return true;
4455                         break;
4456                 case 6:
4457                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4458                                 return true;
4459                         break;
4460                 case 7:
4461                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4462                                 return true;
4463                         break;
4464                 }
4465         }
4466         return false;
4467 }
4468
4469 //==================================================================================
4470
4471 // LordHavoc: this stores temporary data used within the same frame
4472
4473 typedef struct r_framedata_mem_s
4474 {
4475         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4476         size_t size; // how much usable space
4477         size_t current; // how much space in use
4478         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4479         size_t wantedsize; // how much space was allocated
4480         unsigned char *data; // start of real data (16byte aligned)
4481 }
4482 r_framedata_mem_t;
4483
4484 static r_framedata_mem_t *r_framedata_mem;
4485
4486 void R_FrameData_Reset(void)
4487 {
4488         while (r_framedata_mem)
4489         {
4490                 r_framedata_mem_t *next = r_framedata_mem->purge;
4491                 Mem_Free(r_framedata_mem);
4492                 r_framedata_mem = next;
4493         }
4494 }
4495
4496 static void R_FrameData_Resize(void)
4497 {
4498         size_t wantedsize;
4499         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4500         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4501         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4502         {
4503                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4504                 newmem->wantedsize = wantedsize;
4505                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4506                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4507                 newmem->current = 0;
4508                 newmem->mark = 0;
4509                 newmem->purge = r_framedata_mem;
4510                 r_framedata_mem = newmem;
4511         }
4512 }
4513
4514 void R_FrameData_NewFrame(void)
4515 {
4516         R_FrameData_Resize();
4517         if (!r_framedata_mem)
4518                 return;
4519         // if we ran out of space on the last frame, free the old memory now
4520         while (r_framedata_mem->purge)
4521         {
4522                 // repeatedly remove the second item in the list, leaving only head
4523                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4524                 Mem_Free(r_framedata_mem->purge);
4525                 r_framedata_mem->purge = next;
4526         }
4527         // reset the current mem pointer
4528         r_framedata_mem->current = 0;
4529         r_framedata_mem->mark = 0;
4530 }
4531
4532 void *R_FrameData_Alloc(size_t size)
4533 {
4534         void *data;
4535
4536         // align to 16 byte boundary - the data pointer is already aligned, so we
4537         // only need to ensure the size of every allocation is also aligned
4538         size = (size + 15) & ~15;
4539
4540         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4541         {
4542                 // emergency - we ran out of space, allocate more memory
4543                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4544                 R_FrameData_Resize();
4545         }
4546
4547         data = r_framedata_mem->data + r_framedata_mem->current;
4548         r_framedata_mem->current += size;
4549
4550         // count the usage for stats
4551         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4552         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4553
4554         return (void *)data;
4555 }
4556
4557 void *R_FrameData_Store(size_t size, void *data)
4558 {
4559         void *d = R_FrameData_Alloc(size);
4560         if (d && data)
4561                 memcpy(d, data, size);
4562         return d;
4563 }
4564
4565 void R_FrameData_SetMark(void)
4566 {
4567         if (!r_framedata_mem)
4568                 return;
4569         r_framedata_mem->mark = r_framedata_mem->current;
4570 }
4571
4572 void R_FrameData_ReturnToMark(void)
4573 {
4574         if (!r_framedata_mem)
4575                 return;
4576         r_framedata_mem->current = r_framedata_mem->mark;
4577 }
4578
4579 //==================================================================================
4580
4581 // LordHavoc: animcache originally written by Echon, rewritten since then
4582
4583 /**
4584  * Animation cache prevents re-generating mesh data for an animated model
4585  * multiple times in one frame for lighting, shadowing, reflections, etc.
4586  */
4587
4588 void R_AnimCache_Free(void)
4589 {
4590 }
4591
4592 void R_AnimCache_ClearCache(void)
4593 {
4594         int i;
4595         entity_render_t *ent;
4596
4597         for (i = 0;i < r_refdef.scene.numentities;i++)
4598         {
4599                 ent = r_refdef.scene.entities[i];
4600                 ent->animcache_vertex3f = NULL;
4601                 ent->animcache_normal3f = NULL;
4602                 ent->animcache_svector3f = NULL;
4603                 ent->animcache_tvector3f = NULL;
4604                 ent->animcache_vertexmesh = NULL;
4605                 ent->animcache_vertex3fbuffer = NULL;
4606                 ent->animcache_vertexmeshbuffer = NULL;
4607         }
4608 }
4609
4610 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4611 {
4612         int i;
4613
4614         // check if we need the meshbuffers
4615         if (!vid.useinterleavedarrays)
4616                 return;
4617
4618         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4619                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4620         // TODO: upload vertex3f buffer?
4621         if (ent->animcache_vertexmesh)
4622         {
4623                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4624                 for (i = 0;i < numvertices;i++)
4625                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4626                 if (ent->animcache_svector3f)
4627                         for (i = 0;i < numvertices;i++)
4628                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4629                 if (ent->animcache_tvector3f)
4630                         for (i = 0;i < numvertices;i++)
4631                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4632                 if (ent->animcache_normal3f)
4633                         for (i = 0;i < numvertices;i++)
4634                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4635                 // TODO: upload vertexmeshbuffer?
4636         }
4637 }
4638
4639 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4640 {
4641         dp_model_t *model = ent->model;
4642         int numvertices;
4643         // see if it's already cached this frame
4644         if (ent->animcache_vertex3f)
4645         {
4646                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4647                 if (wantnormals || wanttangents)
4648                 {
4649                         if (ent->animcache_normal3f)
4650                                 wantnormals = false;
4651                         if (ent->animcache_svector3f)
4652                                 wanttangents = false;
4653                         if (wantnormals || wanttangents)
4654                         {
4655                                 numvertices = model->surfmesh.num_vertices;
4656                                 if (wantnormals)
4657                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4658                                 if (wanttangents)
4659                                 {
4660                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4661                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4662                                 }
4663                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4664                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4665                         }
4666                 }
4667         }
4668         else
4669         {
4670                 // see if this ent is worth caching
4671                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4672                         return false;
4673                 // get some memory for this entity and generate mesh data
4674                 numvertices = model->surfmesh.num_vertices;
4675                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4676                 if (wantnormals)
4677                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4678                 if (wanttangents)
4679                 {
4680                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4681                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4682                 }
4683                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4684                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4685         }
4686         return true;
4687 }
4688
4689 void R_AnimCache_CacheVisibleEntities(void)
4690 {
4691         int i;
4692         qboolean wantnormals = true;
4693         qboolean wanttangents = !r_showsurfaces.integer;
4694
4695         switch(vid.renderpath)
4696         {
4697         case RENDERPATH_GL20:
4698         case RENDERPATH_D3D9:
4699         case RENDERPATH_D3D10:
4700         case RENDERPATH_D3D11:
4701         case RENDERPATH_GLES2:
4702                 break;
4703         case RENDERPATH_GL11:
4704         case RENDERPATH_GL13:
4705         case RENDERPATH_GLES1:
4706                 wanttangents = false;
4707                 break;
4708         case RENDERPATH_SOFT:
4709                 break;
4710         }
4711
4712         if (r_shownormals.integer)
4713                 wanttangents = wantnormals = true;
4714
4715         // TODO: thread this
4716         // NOTE: R_PrepareRTLights() also caches entities
4717
4718         for (i = 0;i < r_refdef.scene.numentities;i++)
4719                 if (r_refdef.viewcache.entityvisible[i])
4720                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4721 }
4722
4723 //==================================================================================
4724
4725 extern cvar_t r_overheadsprites_pushback;
4726
4727 static void R_View_UpdateEntityLighting (void)
4728 {
4729         int i;
4730         entity_render_t *ent;
4731         vec3_t tempdiffusenormal, avg;
4732         vec_t f, fa, fd, fdd;
4733         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4734
4735         for (i = 0;i < r_refdef.scene.numentities;i++)
4736         {
4737                 ent = r_refdef.scene.entities[i];
4738
4739                 // skip unseen models and models that updated by CSQC
4740                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4741                         continue;
4742
4743                 // skip bsp models
4744                 if (ent->model && (ent->model == cl.worldmodel || ent->model->brush.parentmodel == cl.worldmodel))
4745                 {
4746                         // TODO: use modellight for r_ambient settings on world?
4747                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4748                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4749                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4750                         continue;
4751                 }
4752
4753                 // fetch the lighting from the worldmodel data
4754                 VectorClear(ent->modellight_ambient);
4755                 VectorClear(ent->modellight_diffuse);
4756                 VectorClear(tempdiffusenormal);
4757                 if (ent->flags & RENDER_LIGHT)
4758                 {
4759                         vec3_t org;
4760                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4761
4762                         // complete lightning for lit sprites
4763                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4764                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4765                         {
4766                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4767                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4768                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4769                         }
4770                         else
4771                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4772
4773                         if(ent->flags & RENDER_EQUALIZE)
4774                         {
4775                                 // first fix up ambient lighting...
4776                                 if(r_equalize_entities_minambient.value > 0)
4777                                 {
4778                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4779                                         if(fd > 0)
4780                                         {
4781                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4782                                                 if(fa < r_equalize_entities_minambient.value * fd)
4783                                                 {
4784                                                         // solve:
4785                                                         //   fa'/fd' = minambient
4786                                                         //   fa'+0.25*fd' = fa+0.25*fd
4787                                                         //   ...
4788                                                         //   fa' = fd' * minambient
4789                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4790                                                         //   ...
4791                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4792                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4793                                                         //   ...
4794                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4795                                                         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
4796                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4797                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4798                                                 }
4799                                         }
4800                                 }
4801
4802                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4803                                 {
4804                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4805                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4806                                         f = fa + 0.25 * fd;
4807                                         if(f > 0)
4808                                         {
4809                                                 // adjust brightness and saturation to target
4810                                                 avg[0] = avg[1] = avg[2] = fa / f;
4811                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4812                                                 avg[0] = avg[1] = avg[2] = fd / f;
4813                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4814                                         }
4815                                 }
4816                         }
4817                 }
4818                 else // highly rare
4819                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4820
4821                 // move the light direction into modelspace coordinates for lighting code
4822                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4823                 if(VectorLength2(ent->modellight_lightdir) == 0)
4824                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4825                 VectorNormalize(ent->modellight_lightdir);
4826         }
4827 }
4828
4829 #define MAX_LINEOFSIGHTTRACES 64
4830
4831 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4832 {
4833         int i;
4834         vec3_t boxmins, boxmaxs;
4835         vec3_t start;
4836         vec3_t end;
4837         dp_model_t *model = r_refdef.scene.worldmodel;
4838
4839         if (!model || !model->brush.TraceLineOfSight)
4840                 return true;
4841
4842         // expand the box a little
4843         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4844         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4845         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4846         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4847         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4848         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4849
4850         // return true if eye is inside enlarged box
4851         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4852                 return true;
4853
4854         // try center
4855         VectorCopy(eye, start);
4856         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4857         if (model->brush.TraceLineOfSight(model, start, end))
4858                 return true;
4859
4860         // try various random positions
4861         for (i = 0;i < numsamples;i++)
4862         {
4863                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4864                 if (model->brush.TraceLineOfSight(model, start, end))
4865                         return true;
4866         }
4867
4868         return false;
4869 }
4870
4871
4872 static void R_View_UpdateEntityVisible (void)
4873 {
4874         int i;
4875         int renderimask;
4876         int samples;
4877         entity_render_t *ent;
4878
4879         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4880                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4881                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4882                 :                                                          RENDER_EXTERIORMODEL;
4883         if (!r_drawviewmodel.integer)
4884                 renderimask |= RENDER_VIEWMODEL;
4885         if (!r_drawexteriormodel.integer)
4886                 renderimask |= RENDER_EXTERIORMODEL;
4887         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4888         {
4889                 // worldmodel can check visibility
4890                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4891                 for (i = 0;i < r_refdef.scene.numentities;i++)
4892                 {
4893                         ent = r_refdef.scene.entities[i];
4894                         if (!(ent->flags & renderimask))
4895                         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)))
4896                         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))
4897                                 r_refdef.viewcache.entityvisible[i] = true;
4898                 }
4899         }
4900         else
4901         {
4902                 // no worldmodel or it can't check visibility
4903                 for (i = 0;i < r_refdef.scene.numentities;i++)
4904                 {
4905                         ent = r_refdef.scene.entities[i];
4906                         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));
4907                 }
4908         }
4909         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4910                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4911         {
4912                 for (i = 0;i < r_refdef.scene.numentities;i++)
4913                 {
4914                         if (!r_refdef.viewcache.entityvisible[i])
4915                                 continue;
4916                         ent = r_refdef.scene.entities[i];
4917                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4918                         {
4919                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4920                                 if (samples < 0)
4921                                         continue; // temp entities do pvs only
4922                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4923                                         ent->last_trace_visibility = realtime;
4924                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4925                                         r_refdef.viewcache.entityvisible[i] = 0;
4926                         }
4927                 }
4928         }
4929 }
4930
4931 /// only used if skyrendermasked, and normally returns false
4932 static int R_DrawBrushModelsSky (void)
4933 {
4934         int i, sky;
4935         entity_render_t *ent;
4936
4937         sky = false;
4938         for (i = 0;i < r_refdef.scene.numentities;i++)
4939         {
4940                 if (!r_refdef.viewcache.entityvisible[i])
4941                         continue;
4942                 ent = r_refdef.scene.entities[i];
4943                 if (!ent->model || !ent->model->DrawSky)
4944                         continue;
4945                 ent->model->DrawSky(ent);
4946                 sky = true;
4947         }
4948         return sky;
4949 }
4950
4951 static void R_DrawNoModel(entity_render_t *ent);
4952 static void R_DrawModels(void)
4953 {
4954         int i;
4955         entity_render_t *ent;
4956
4957         for (i = 0;i < r_refdef.scene.numentities;i++)
4958         {
4959                 if (!r_refdef.viewcache.entityvisible[i])
4960                         continue;
4961                 ent = r_refdef.scene.entities[i];
4962                 r_refdef.stats.entities++;
4963                 /*
4964                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4965                 {
4966                         vec3_t f, l, u, o;
4967                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4968                         Con_Printf("R_DrawModels\n");
4969                         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]);
4970                         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);
4971                         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);
4972                 }
4973                 */
4974                 if (ent->model && ent->model->Draw != NULL)
4975                         ent->model->Draw(ent);
4976                 else
4977                         R_DrawNoModel(ent);
4978         }
4979 }
4980
4981 static void R_DrawModelsDepth(void)
4982 {
4983         int i;
4984         entity_render_t *ent;
4985
4986         for (i = 0;i < r_refdef.scene.numentities;i++)
4987         {
4988                 if (!r_refdef.viewcache.entityvisible[i])
4989                         continue;
4990                 ent = r_refdef.scene.entities[i];
4991                 if (ent->model && ent->model->DrawDepth != NULL)
4992                         ent->model->DrawDepth(ent);
4993         }
4994 }
4995
4996 static void R_DrawModelsDebug(void)
4997 {
4998         int i;
4999         entity_render_t *ent;
5000
5001         for (i = 0;i < r_refdef.scene.numentities;i++)
5002         {
5003                 if (!r_refdef.viewcache.entityvisible[i])
5004                         continue;
5005                 ent = r_refdef.scene.entities[i];
5006                 if (ent->model && ent->model->DrawDebug != NULL)
5007                         ent->model->DrawDebug(ent);
5008         }
5009 }
5010
5011 static void R_DrawModelsAddWaterPlanes(void)
5012 {
5013         int i;
5014         entity_render_t *ent;
5015
5016         for (i = 0;i < r_refdef.scene.numentities;i++)
5017         {
5018                 if (!r_refdef.viewcache.entityvisible[i])
5019                         continue;
5020                 ent = r_refdef.scene.entities[i];
5021                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5022                         ent->model->DrawAddWaterPlanes(ent);
5023         }
5024 }
5025
5026 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}};
5027
5028 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5029 {
5030         if (r_hdr_irisadaptation.integer)
5031         {
5032                 vec3_t p;
5033                 vec3_t ambient;
5034                 vec3_t diffuse;
5035                 vec3_t diffusenormal;
5036                 vec3_t forward;
5037                 vec_t brightness = 0.0f;
5038                 vec_t goal;
5039                 vec_t current;
5040                 vec_t d;
5041                 int c;
5042                 VectorCopy(r_refdef.view.forward, forward);
5043                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5044                 {
5045                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5046                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5047                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5048                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5049                         d = DotProduct(forward, diffusenormal);
5050                         brightness += VectorLength(ambient);
5051                         if (d > 0)
5052                                 brightness += d * VectorLength(diffuse);
5053                 }
5054                 brightness *= 1.0f / c;
5055                 brightness += 0.00001f; // make sure it's never zero
5056                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5057                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5058                 current = r_hdr_irisadaptation_value.value;
5059                 if (current < goal)
5060                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5061                 else if (current > goal)
5062                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5063                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5064                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5065         }
5066         else if (r_hdr_irisadaptation_value.value != 1.0f)
5067                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5068 }
5069
5070 static void R_View_SetFrustum(const int *scissor)
5071 {
5072         int i;
5073         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5074         vec3_t forward, left, up, origin, v;
5075
5076         if(scissor)
5077         {
5078                 // flipped x coordinates (because x points left here)
5079                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5080                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5081
5082                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5083                 switch(vid.renderpath)
5084                 {
5085                         case RENDERPATH_D3D9:
5086                         case RENDERPATH_D3D10:
5087                         case RENDERPATH_D3D11:
5088                                 // non-flipped y coordinates
5089                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5090                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5091                                 break;
5092                         case RENDERPATH_SOFT:
5093                         case RENDERPATH_GL11:
5094                         case RENDERPATH_GL13:
5095                         case RENDERPATH_GL20:
5096                         case RENDERPATH_GLES1:
5097                         case RENDERPATH_GLES2:
5098                                 // non-flipped y coordinates
5099                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5100                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5101                                 break;
5102                 }
5103         }
5104
5105         // we can't trust r_refdef.view.forward and friends in reflected scenes
5106         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5107
5108 #if 0
5109         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5110         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5111         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5112         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5113         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5114         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5115         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5116         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5117         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5118         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5119         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5120         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5121 #endif
5122
5123 #if 0
5124         zNear = r_refdef.nearclip;
5125         nudge = 1.0 - 1.0 / (1<<23);
5126         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5127         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5128         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5129         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5130         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5131         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5132         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5133         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5134 #endif
5135
5136
5137
5138 #if 0
5139         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5140         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5141         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5142         r_refdef.view.frustum[0].dist = m[15] - m[12];
5143
5144         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5145         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5146         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5147         r_refdef.view.frustum[1].dist = m[15] + m[12];
5148
5149         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5150         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5151         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5152         r_refdef.view.frustum[2].dist = m[15] - m[13];
5153
5154         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5155         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5156         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5157         r_refdef.view.frustum[3].dist = m[15] + m[13];
5158
5159         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5160         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5161         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5162         r_refdef.view.frustum[4].dist = m[15] - m[14];
5163
5164         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5165         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5166         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5167         r_refdef.view.frustum[5].dist = m[15] + m[14];
5168 #endif
5169
5170         if (r_refdef.view.useperspective)
5171         {
5172                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5173                 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]);
5174                 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]);
5175                 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]);
5176                 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]);
5177
5178                 // then the normals from the corners relative to origin
5179                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5180                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5181                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5182                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5183
5184                 // in a NORMAL view, forward cross left == up
5185                 // in a REFLECTED view, forward cross left == down
5186                 // so our cross products above need to be adjusted for a left handed coordinate system
5187                 CrossProduct(forward, left, v);
5188                 if(DotProduct(v, up) < 0)
5189                 {
5190                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5191                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5192                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5193                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5194                 }
5195
5196                 // Leaving those out was a mistake, those were in the old code, and they
5197                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5198                 // I couldn't reproduce it after adding those normalizations. --blub
5199                 VectorNormalize(r_refdef.view.frustum[0].normal);
5200                 VectorNormalize(r_refdef.view.frustum[1].normal);
5201                 VectorNormalize(r_refdef.view.frustum[2].normal);
5202                 VectorNormalize(r_refdef.view.frustum[3].normal);
5203
5204                 // make the corners absolute
5205                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5206                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5207                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5208                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5209
5210                 // one more normal
5211                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5212
5213                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5214                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5215                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5216                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5217                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5218         }
5219         else
5220         {
5221                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5222                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5223                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5224                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5225                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5226                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5227                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5228                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5229                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5230                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5231         }
5232         r_refdef.view.numfrustumplanes = 5;
5233
5234         if (r_refdef.view.useclipplane)
5235         {
5236                 r_refdef.view.numfrustumplanes = 6;
5237                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5238         }
5239
5240         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5241                 PlaneClassify(r_refdef.view.frustum + i);
5242
5243         // LordHavoc: note to all quake engine coders, Quake had a special case
5244         // for 90 degrees which assumed a square view (wrong), so I removed it,
5245         // Quake2 has it disabled as well.
5246
5247         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5248         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5249         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5250         //PlaneClassify(&frustum[0]);
5251
5252         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5253         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5254         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5255         //PlaneClassify(&frustum[1]);
5256
5257         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5258         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5259         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5260         //PlaneClassify(&frustum[2]);
5261
5262         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5263         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5264         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5265         //PlaneClassify(&frustum[3]);
5266
5267         // nearclip plane
5268         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5269         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5270         //PlaneClassify(&frustum[4]);
5271 }
5272
5273 static void R_View_UpdateWithScissor(const int *myscissor)
5274 {
5275         R_Main_ResizeViewCache();
5276         R_View_SetFrustum(myscissor);
5277         R_View_WorldVisibility(r_refdef.view.useclipplane);
5278         R_View_UpdateEntityVisible();
5279         R_View_UpdateEntityLighting();
5280         R_AnimCache_CacheVisibleEntities();
5281 }
5282
5283 static void R_View_Update(void)
5284 {
5285         R_Main_ResizeViewCache();
5286         R_View_SetFrustum(NULL);
5287         R_View_WorldVisibility(r_refdef.view.useclipplane);
5288         R_View_UpdateEntityVisible();
5289         R_View_UpdateEntityLighting();
5290         R_AnimCache_CacheVisibleEntities();
5291 }
5292
5293 float viewscalefpsadjusted = 1.0f;
5294
5295 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5296 {
5297         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5298         scale = bound(0.03125f, scale, 1.0f);
5299         *outwidth = (int)ceil(width * scale);
5300         *outheight = (int)ceil(height * scale);
5301 }
5302
5303 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5304 {
5305         const float *customclipplane = NULL;
5306         float plane[4];
5307         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5308         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5309         {
5310                 // LordHavoc: couldn't figure out how to make this approach the
5311                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5312                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5313                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5314                         dist = r_refdef.view.clipplane.dist;
5315                 plane[0] = r_refdef.view.clipplane.normal[0];
5316                 plane[1] = r_refdef.view.clipplane.normal[1];
5317                 plane[2] = r_refdef.view.clipplane.normal[2];
5318                 plane[3] = -dist;
5319                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5320         }
5321
5322         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5323         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5324
5325         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5326         if (!r_refdef.view.useperspective)
5327                 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);
5328         else if (vid.stencil && r_useinfinitefarclip.integer)
5329                 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);
5330         else
5331                 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);
5332         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5333         R_SetViewport(&r_refdef.view.viewport);
5334         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5335         {
5336                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5337                 float screenplane[4];
5338                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5339                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5340                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5341                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5342                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5343         }
5344 }
5345
5346 void R_EntityMatrix(const matrix4x4_t *matrix)
5347 {
5348         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5349         {
5350                 gl_modelmatrixchanged = false;
5351                 gl_modelmatrix = *matrix;
5352                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5353                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5354                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5355                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5356                 CHECKGLERROR
5357                 switch(vid.renderpath)
5358                 {
5359                 case RENDERPATH_D3D9:
5360 #ifdef SUPPORTD3D
5361                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5362                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5363 #endif
5364                         break;
5365                 case RENDERPATH_D3D10:
5366                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5367                         break;
5368                 case RENDERPATH_D3D11:
5369                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5370                         break;
5371                 case RENDERPATH_GL11:
5372                 case RENDERPATH_GL13:
5373                 case RENDERPATH_GLES1:
5374                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5375                         break;
5376                 case RENDERPATH_SOFT:
5377                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5378                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5379                         break;
5380                 case RENDERPATH_GL20:
5381                 case RENDERPATH_GLES2:
5382                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5383                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5384                         break;
5385                 }
5386         }
5387 }
5388
5389 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5390 {
5391         r_viewport_t viewport;
5392
5393         CHECKGLERROR
5394
5395         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5396         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);
5397         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5398         R_SetViewport(&viewport);
5399         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5400         GL_Color(1, 1, 1, 1);
5401         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5402         GL_BlendFunc(GL_ONE, GL_ZERO);
5403         GL_ScissorTest(false);
5404         GL_DepthMask(false);
5405         GL_DepthRange(0, 1);
5406         GL_DepthTest(false);
5407         GL_DepthFunc(GL_LEQUAL);
5408         R_EntityMatrix(&identitymatrix);
5409         R_Mesh_ResetTextureState();
5410         GL_PolygonOffset(0, 0);
5411         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5412         switch(vid.renderpath)
5413         {
5414         case RENDERPATH_GL11:
5415         case RENDERPATH_GL13:
5416         case RENDERPATH_GL20:
5417         case RENDERPATH_GLES1:
5418         case RENDERPATH_GLES2:
5419                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5420                 break;
5421         case RENDERPATH_D3D9:
5422         case RENDERPATH_D3D10:
5423         case RENDERPATH_D3D11:
5424         case RENDERPATH_SOFT:
5425                 break;
5426         }
5427         GL_CullFace(GL_NONE);
5428
5429         CHECKGLERROR
5430 }
5431
5432 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5433 {
5434         DrawQ_Finish();
5435
5436         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5437 }
5438
5439 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5440 {
5441         DrawQ_Finish();
5442
5443         R_SetupView(true, fbo, depthtexture, colortexture);
5444         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5445         GL_Color(1, 1, 1, 1);
5446         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5447         GL_BlendFunc(GL_ONE, GL_ZERO);
5448         GL_ScissorTest(true);
5449         GL_DepthMask(true);
5450         GL_DepthRange(0, 1);
5451         GL_DepthTest(true);
5452         GL_DepthFunc(GL_LEQUAL);
5453         R_EntityMatrix(&identitymatrix);
5454         R_Mesh_ResetTextureState();
5455         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5456         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5457         switch(vid.renderpath)
5458         {
5459         case RENDERPATH_GL11:
5460         case RENDERPATH_GL13:
5461         case RENDERPATH_GL20:
5462         case RENDERPATH_GLES1:
5463         case RENDERPATH_GLES2:
5464                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5465                 break;
5466         case RENDERPATH_D3D9:
5467         case RENDERPATH_D3D10:
5468         case RENDERPATH_D3D11:
5469         case RENDERPATH_SOFT:
5470                 break;
5471         }
5472         GL_CullFace(r_refdef.view.cullface_back);
5473 }
5474
5475 /*
5476 ================
5477 R_RenderView_UpdateViewVectors
5478 ================
5479 */
5480 void R_RenderView_UpdateViewVectors(void)
5481 {
5482         // break apart the view matrix into vectors for various purposes
5483         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5484         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5485         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5486         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5487         // make an inverted copy of the view matrix for tracking sprites
5488         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5489 }
5490
5491 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5492 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5493
5494 static void R_Water_StartFrame(void)
5495 {
5496         int i;
5497         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5498         r_waterstate_waterplane_t *p;
5499         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5500
5501         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5502                 return;
5503
5504         switch(vid.renderpath)
5505         {
5506         case RENDERPATH_GL20:
5507         case RENDERPATH_D3D9:
5508         case RENDERPATH_D3D10:
5509         case RENDERPATH_D3D11:
5510         case RENDERPATH_SOFT:
5511         case RENDERPATH_GLES2:
5512                 break;
5513         case RENDERPATH_GL11:
5514         case RENDERPATH_GL13:
5515         case RENDERPATH_GLES1:
5516                 return;
5517         }
5518
5519         // set waterwidth and waterheight to the water resolution that will be
5520         // used (often less than the screen resolution for faster rendering)
5521         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5522
5523         // calculate desired texture sizes
5524         // can't use water if the card does not support the texture size
5525         if (!r_water.integer || r_showsurfaces.integer)
5526                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5527         else if (vid.support.arb_texture_non_power_of_two)
5528         {
5529                 texturewidth = waterwidth;
5530                 textureheight = waterheight;
5531                 camerawidth = waterwidth;
5532                 cameraheight = waterheight;
5533         }
5534         else
5535         {
5536                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5537                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5538                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5539                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5540         }
5541
5542         // allocate textures as needed
5543         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))
5544         {
5545                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5546                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5547                 {
5548                         if (p->texture_refraction)
5549                                 R_FreeTexture(p->texture_refraction);
5550                         p->texture_refraction = NULL;
5551                         if (p->fbo_refraction)
5552                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5553                         p->fbo_refraction = 0;
5554                         if (p->texture_reflection)
5555                                 R_FreeTexture(p->texture_reflection);
5556                         p->texture_reflection = NULL;
5557                         if (p->fbo_reflection)
5558                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5559                         p->fbo_reflection = 0;
5560                         if (p->texture_camera)
5561                                 R_FreeTexture(p->texture_camera);
5562                         p->texture_camera = NULL;
5563                         if (p->fbo_camera)
5564                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5565                         p->fbo_camera = 0;
5566                 }
5567                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5568                 r_fb.water.texturewidth = texturewidth;
5569                 r_fb.water.textureheight = textureheight;
5570                 r_fb.water.camerawidth = camerawidth;
5571                 r_fb.water.cameraheight = cameraheight;
5572         }
5573
5574         if (r_fb.water.texturewidth)
5575         {
5576                 int scaledwidth, scaledheight;
5577
5578                 r_fb.water.enabled = true;
5579
5580                 // water resolution is usually reduced
5581                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5582                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5583                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5584
5585                 // set up variables that will be used in shader setup
5586                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5587                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5588                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5589                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5590         }
5591
5592         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5593         r_fb.water.numwaterplanes = 0;
5594 }
5595
5596 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5597 {
5598         int planeindex, bestplaneindex, vertexindex;
5599         vec3_t mins, maxs, normal, center, v, n;
5600         vec_t planescore, bestplanescore;
5601         mplane_t plane;
5602         r_waterstate_waterplane_t *p;
5603         texture_t *t = R_GetCurrentTexture(surface->texture);
5604
5605         rsurface.texture = t;
5606         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5607         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5608         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5609                 return;
5610         // average the vertex normals, find the surface bounds (after deformvertexes)
5611         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5612         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5613         VectorCopy(n, normal);
5614         VectorCopy(v, mins);
5615         VectorCopy(v, maxs);
5616         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5617         {
5618                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5619                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5620                 VectorAdd(normal, n, normal);
5621                 mins[0] = min(mins[0], v[0]);
5622                 mins[1] = min(mins[1], v[1]);
5623                 mins[2] = min(mins[2], v[2]);
5624                 maxs[0] = max(maxs[0], v[0]);
5625                 maxs[1] = max(maxs[1], v[1]);
5626                 maxs[2] = max(maxs[2], v[2]);
5627         }
5628         VectorNormalize(normal);
5629         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5630
5631         VectorCopy(normal, plane.normal);
5632         VectorNormalize(plane.normal);
5633         plane.dist = DotProduct(center, plane.normal);
5634         PlaneClassify(&plane);
5635         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5636         {
5637                 // skip backfaces (except if nocullface is set)
5638 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5639 //                      return;
5640                 VectorNegate(plane.normal, plane.normal);
5641                 plane.dist *= -1;
5642                 PlaneClassify(&plane);
5643         }
5644
5645
5646         // find a matching plane if there is one
5647         bestplaneindex = -1;
5648         bestplanescore = 1048576.0f;
5649         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5650         {
5651                 if(p->camera_entity == t->camera_entity)
5652                 {
5653                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5654                         if (bestplaneindex < 0 || bestplanescore > planescore)
5655                         {
5656                                 bestplaneindex = planeindex;
5657                                 bestplanescore = planescore;
5658                         }
5659                 }
5660         }
5661         planeindex = bestplaneindex;
5662         p = r_fb.water.waterplanes + planeindex;
5663
5664         // if this surface does not fit any known plane rendered this frame, add one
5665         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5666         {
5667                 // store the new plane
5668                 planeindex = r_fb.water.numwaterplanes++;
5669                 p = r_fb.water.waterplanes + planeindex;
5670                 p->plane = plane;
5671                 // clear materialflags and pvs
5672                 p->materialflags = 0;
5673                 p->pvsvalid = false;
5674                 p->camera_entity = t->camera_entity;
5675                 VectorCopy(mins, p->mins);
5676                 VectorCopy(maxs, p->maxs);
5677         }
5678         else
5679         {
5680                 // merge mins/maxs when we're adding this surface to the plane
5681                 p->mins[0] = min(p->mins[0], mins[0]);
5682                 p->mins[1] = min(p->mins[1], mins[1]);
5683                 p->mins[2] = min(p->mins[2], mins[2]);
5684                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5685                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5686                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5687         }
5688         // merge this surface's materialflags into the waterplane
5689         p->materialflags |= t->currentmaterialflags;
5690         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5691         {
5692                 // merge this surface's PVS into the waterplane
5693                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5694                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5695                 {
5696                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5697                         p->pvsvalid = true;
5698                 }
5699         }
5700 }
5701
5702 extern cvar_t r_drawparticles;
5703 extern cvar_t r_drawdecals;
5704
5705 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5706 {
5707         int myscissor[4];
5708         r_refdef_view_t originalview;
5709         r_refdef_view_t myview;
5710         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;
5711         r_waterstate_waterplane_t *p;
5712         vec3_t visorigin;
5713         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5714         char vabuf[1024];
5715
5716         originalview = r_refdef.view;
5717
5718         // lowquality hack, temporarily shut down some cvars and restore afterwards
5719         qualityreduction = r_water_lowquality.integer;
5720         if (qualityreduction > 0)
5721         {
5722                 if (qualityreduction >= 1)
5723                 {
5724                         old_r_shadows = r_shadows.integer;
5725                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5726                         old_r_dlight = r_shadow_realtime_dlight.integer;
5727                         Cvar_SetValueQuick(&r_shadows, 0);
5728                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5729                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5730                 }
5731                 if (qualityreduction >= 2)
5732                 {
5733                         old_r_dynamic = r_dynamic.integer;
5734                         old_r_particles = r_drawparticles.integer;
5735                         old_r_decals = r_drawdecals.integer;
5736                         Cvar_SetValueQuick(&r_dynamic, 0);
5737                         Cvar_SetValueQuick(&r_drawparticles, 0);
5738                         Cvar_SetValueQuick(&r_drawdecals, 0);
5739                 }
5740         }
5741
5742         // make sure enough textures are allocated
5743         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5744         {
5745                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5746                 {
5747                         if (!p->texture_refraction)
5748                                 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);
5749                         if (!p->texture_refraction)
5750                                 goto error;
5751                         if (usewaterfbo)
5752                         {
5753                                 if (r_fb.water.depthtexture == NULL)
5754                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5755                                 if (p->fbo_refraction == 0)
5756                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5757                         }
5758                 }
5759                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5760                 {
5761                         if (!p->texture_camera)
5762                                 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);
5763                         if (!p->texture_camera)
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_camera == 0)
5770                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5771                         }
5772                 }
5773
5774                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5775                 {
5776                         if (!p->texture_reflection)
5777                                 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);
5778                         if (!p->texture_reflection)
5779                                 goto error;
5780                         if (usewaterfbo)
5781                         {
5782                                 if (r_fb.water.depthtexture == NULL)
5783                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5784                                 if (p->fbo_reflection == 0)
5785                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5786                         }
5787                 }
5788         }
5789
5790         // render views
5791         r_refdef.view = originalview;
5792         r_refdef.view.showdebug = false;
5793         r_refdef.view.width = r_fb.water.waterwidth;
5794         r_refdef.view.height = r_fb.water.waterheight;
5795         r_refdef.view.useclipplane = true;
5796         myview = r_refdef.view;
5797         r_fb.water.renderingscene = true;
5798         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5799         {
5800                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5801                 {
5802                         r_refdef.view = myview;
5803                         if(r_water_scissormode.integer)
5804                         {
5805                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5806                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5807                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5808                         }
5809
5810                         // render reflected scene and copy into texture
5811                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5812                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5813                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5814                         r_refdef.view.clipplane = p->plane;
5815                         // reverse the cullface settings for this render
5816                         r_refdef.view.cullface_front = GL_FRONT;
5817                         r_refdef.view.cullface_back = GL_BACK;
5818                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5819                         {
5820                                 r_refdef.view.usecustompvs = true;
5821                                 if (p->pvsvalid)
5822                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5823                                 else
5824                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5825                         }
5826
5827                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5828                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5829                         R_ClearScreen(r_refdef.fogenabled);
5830                         if(r_water_scissormode.integer & 2)
5831                                 R_View_UpdateWithScissor(myscissor);
5832                         else
5833                                 R_View_Update();
5834                         if(r_water_scissormode.integer & 1)
5835                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5836                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5837
5838                         if (!p->fbo_reflection)
5839                                 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);
5840                         r_fb.water.hideplayer = false;
5841                 }
5842
5843                 // render the normal view scene and copy into texture
5844                 // (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)
5845                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5846                 {
5847                         r_refdef.view = myview;
5848                         if(r_water_scissormode.integer)
5849                         {
5850                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5851                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5852                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5853                         }
5854
5855                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5856
5857                         r_refdef.view.clipplane = p->plane;
5858                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5859                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5860
5861                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5862                         {
5863                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5864                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5865                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5866                                 R_RenderView_UpdateViewVectors();
5867                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5868                                 {
5869                                         r_refdef.view.usecustompvs = true;
5870                                         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);
5871                                 }
5872                         }
5873
5874                         PlaneClassify(&r_refdef.view.clipplane);
5875
5876                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5877                         R_ClearScreen(r_refdef.fogenabled);
5878                         if(r_water_scissormode.integer & 2)
5879                                 R_View_UpdateWithScissor(myscissor);
5880                         else
5881                                 R_View_Update();
5882                         if(r_water_scissormode.integer & 1)
5883                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5884                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5885
5886                         if (!p->fbo_refraction)
5887                                 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);
5888                         r_fb.water.hideplayer = false;
5889                 }
5890                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5891                 {
5892                         r_refdef.view = myview;
5893
5894                         r_refdef.view.clipplane = p->plane;
5895                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5896                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5897
5898                         r_refdef.view.width = r_fb.water.camerawidth;
5899                         r_refdef.view.height = r_fb.water.cameraheight;
5900                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5901                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5902                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5903                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5904
5905                         if(p->camera_entity)
5906                         {
5907                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5908                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5909                         }
5910
5911                         // note: all of the view is used for displaying... so
5912                         // there is no use in scissoring
5913
5914                         // reverse the cullface settings for this render
5915                         r_refdef.view.cullface_front = GL_FRONT;
5916                         r_refdef.view.cullface_back = GL_BACK;
5917                         // also reverse the view matrix
5918                         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
5919                         R_RenderView_UpdateViewVectors();
5920                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5921                         {
5922                                 r_refdef.view.usecustompvs = true;
5923                                 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);
5924                         }
5925                         
5926                         // camera needs no clipplane
5927                         r_refdef.view.useclipplane = false;
5928
5929                         PlaneClassify(&r_refdef.view.clipplane);
5930
5931                         r_fb.water.hideplayer = false;
5932
5933                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5934                         R_ClearScreen(r_refdef.fogenabled);
5935                         R_View_Update();
5936                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5937
5938                         if (!p->fbo_camera)
5939                                 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);
5940                         r_fb.water.hideplayer = false;
5941                 }
5942
5943         }
5944         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5945         r_fb.water.renderingscene = false;
5946         r_refdef.view = originalview;
5947         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5948         if (!r_fb.water.depthtexture)
5949                 R_ClearScreen(r_refdef.fogenabled);
5950         R_View_Update();
5951         goto finish;
5952 error:
5953         r_refdef.view = originalview;
5954         r_fb.water.renderingscene = false;
5955         Cvar_SetValueQuick(&r_water, 0);
5956         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5957 finish:
5958         // lowquality hack, restore cvars
5959         if (qualityreduction > 0)
5960         {
5961                 if (qualityreduction >= 1)
5962                 {
5963                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5964                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5965                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5966                 }
5967                 if (qualityreduction >= 2)
5968                 {
5969                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5970                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5971                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5972                 }
5973         }
5974 }
5975
5976 static void R_Bloom_StartFrame(void)
5977 {
5978         int i;
5979         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5980         int viewwidth, viewheight;
5981         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
5982         textype_t textype = TEXTYPE_COLORBUFFER;
5983
5984         switch (vid.renderpath)
5985         {
5986         case RENDERPATH_GL20:
5987                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
5988                 if (vid.support.ext_framebuffer_object)
5989                 {
5990                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5991                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5992                 }
5993                 break;
5994         case RENDERPATH_GL11:
5995         case RENDERPATH_GL13:
5996         case RENDERPATH_GLES1:
5997         case RENDERPATH_GLES2:
5998         case RENDERPATH_D3D9:
5999         case RENDERPATH_D3D10:
6000         case RENDERPATH_D3D11:
6001                 r_fb.usedepthtextures = false;
6002                 break;
6003         case RENDERPATH_SOFT:
6004                 r_fb.usedepthtextures = true;
6005                 break;
6006         }
6007
6008         if (r_viewscale_fpsscaling.integer)
6009         {
6010                 double actualframetime;
6011                 double targetframetime;
6012                 double adjust;
6013                 actualframetime = r_refdef.lastdrawscreentime;
6014                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6015                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6016                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6017                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6018                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6019                 viewscalefpsadjusted += adjust;
6020                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6021         }
6022         else
6023                 viewscalefpsadjusted = 1.0f;
6024
6025         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6026
6027         switch(vid.renderpath)
6028         {
6029         case RENDERPATH_GL20:
6030         case RENDERPATH_D3D9:
6031         case RENDERPATH_D3D10:
6032         case RENDERPATH_D3D11:
6033         case RENDERPATH_SOFT:
6034         case RENDERPATH_GLES2:
6035                 break;
6036         case RENDERPATH_GL11:
6037         case RENDERPATH_GL13:
6038         case RENDERPATH_GLES1:
6039                 return;
6040         }
6041
6042         // set bloomwidth and bloomheight to the bloom resolution that will be
6043         // used (often less than the screen resolution for faster rendering)
6044         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6045         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6046         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6047         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6048         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6049
6050         // calculate desired texture sizes
6051         if (vid.support.arb_texture_non_power_of_two)
6052         {
6053                 screentexturewidth = vid.width;
6054                 screentextureheight = vid.height;
6055                 bloomtexturewidth = r_fb.bloomwidth;
6056                 bloomtextureheight = r_fb.bloomheight;
6057         }
6058         else
6059         {
6060                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6061                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6062                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6063                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6064         }
6065
6066         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))
6067         {
6068                 Cvar_SetValueQuick(&r_bloom, 0);
6069                 Cvar_SetValueQuick(&r_motionblur, 0);
6070                 Cvar_SetValueQuick(&r_damageblur, 0);
6071         }
6072
6073         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6074          && !r_bloom.integer
6075          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6076          && !useviewfbo
6077          && r_viewscale.value == 1.0f
6078          && !r_viewscale_fpsscaling.integer)
6079                 screentexturewidth = screentextureheight = 0;
6080         if (!r_bloom.integer)
6081                 bloomtexturewidth = bloomtextureheight = 0;
6082
6083         // allocate textures as needed
6084         if (r_fb.screentexturewidth != screentexturewidth
6085          || r_fb.screentextureheight != screentextureheight
6086          || r_fb.bloomtexturewidth != bloomtexturewidth
6087          || r_fb.bloomtextureheight != bloomtextureheight
6088          || r_fb.textype != textype
6089          || useviewfbo != (r_fb.fbo != 0))
6090         {
6091                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6092                 {
6093                         if (r_fb.bloomtexture[i])
6094                                 R_FreeTexture(r_fb.bloomtexture[i]);
6095                         r_fb.bloomtexture[i] = NULL;
6096
6097                         if (r_fb.bloomfbo[i])
6098                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6099                         r_fb.bloomfbo[i] = 0;
6100                 }
6101
6102                 if (r_fb.fbo)
6103                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6104                 r_fb.fbo = 0;
6105
6106                 if (r_fb.colortexture)
6107                         R_FreeTexture(r_fb.colortexture);
6108                 r_fb.colortexture = NULL;
6109
6110                 if (r_fb.depthtexture)
6111                         R_FreeTexture(r_fb.depthtexture);
6112                 r_fb.depthtexture = NULL;
6113
6114                 if (r_fb.ghosttexture)
6115                         R_FreeTexture(r_fb.ghosttexture);
6116                 r_fb.ghosttexture = NULL;
6117
6118                 r_fb.screentexturewidth = screentexturewidth;
6119                 r_fb.screentextureheight = screentextureheight;
6120                 r_fb.bloomtexturewidth = bloomtexturewidth;
6121                 r_fb.bloomtextureheight = bloomtextureheight;
6122                 r_fb.textype = textype;
6123
6124                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6125                 {
6126                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6127                                 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);
6128                         r_fb.ghosttexture_valid = false;
6129                         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);
6130                         if (useviewfbo)
6131                         {
6132                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6133                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6134                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6135                         }
6136                 }
6137
6138                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6139                 {
6140                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6141                         {
6142                                 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);
6143                                 if (useviewfbo)
6144                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6145                         }
6146                 }
6147         }
6148
6149         // bloom texture is a different resolution
6150         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6151         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6152         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6153         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6154         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6155
6156         // set up a texcoord array for the full resolution screen image
6157         // (we have to keep this around to copy back during final render)
6158         r_fb.screentexcoord2f[0] = 0;
6159         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6160         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6161         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6162         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6163         r_fb.screentexcoord2f[5] = 0;
6164         r_fb.screentexcoord2f[6] = 0;
6165         r_fb.screentexcoord2f[7] = 0;
6166
6167         // set up a texcoord array for the reduced resolution bloom image
6168         // (which will be additive blended over the screen image)
6169         r_fb.bloomtexcoord2f[0] = 0;
6170         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6171         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6172         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6173         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6174         r_fb.bloomtexcoord2f[5] = 0;
6175         r_fb.bloomtexcoord2f[6] = 0;
6176         r_fb.bloomtexcoord2f[7] = 0;
6177
6178         switch(vid.renderpath)
6179         {
6180         case RENDERPATH_GL11:
6181         case RENDERPATH_GL13:
6182         case RENDERPATH_GL20:
6183         case RENDERPATH_SOFT:
6184         case RENDERPATH_GLES1:
6185         case RENDERPATH_GLES2:
6186                 break;
6187         case RENDERPATH_D3D9:
6188         case RENDERPATH_D3D10:
6189         case RENDERPATH_D3D11:
6190                 {
6191                         int i;
6192                         for (i = 0;i < 4;i++)
6193                         {
6194                                 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6195                                 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6196                                 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6197                                 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6198                         }
6199                 }
6200                 break;
6201         }
6202
6203         R_Viewport_InitOrtho(&r_fb.bloomviewport, &identitymatrix, r_refdef.view.x, (r_fb.bloomfbo[0] ? r_fb.bloomtextureheight : vid.height) - r_fb.bloomheight - r_refdef.view.y, r_fb.bloomwidth, r_fb.bloomheight, 0, 0, 1, 1, -10, 100, NULL);
6204
6205         if (r_fb.fbo)
6206                 r_refdef.view.clear = true;
6207 }
6208
6209 static void R_Bloom_MakeTexture(void)
6210 {
6211         int x, range, dir;
6212         float xoffset, yoffset, r, brighten;
6213         rtexture_t *intex;
6214         float colorscale = r_bloom_colorscale.value;
6215
6216         r_refdef.stats.bloom++;
6217
6218         if (!r_fb.fbo)
6219         {
6220                 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);
6221                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6222         }
6223
6224         // scale down screen texture to the bloom texture size
6225         CHECKGLERROR
6226         r_fb.bloomindex = 0;
6227         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6228         R_SetViewport(&r_fb.bloomviewport);
6229         GL_BlendFunc(GL_ONE, GL_ZERO);
6230         GL_Color(colorscale, colorscale, colorscale, 1);
6231         // 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...
6232         switch(vid.renderpath)
6233         {
6234         case RENDERPATH_GL11:
6235         case RENDERPATH_GL13:
6236         case RENDERPATH_GL20:
6237         case RENDERPATH_GLES1:
6238         case RENDERPATH_GLES2:
6239         case RENDERPATH_SOFT:
6240                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6241                 break;
6242         case RENDERPATH_D3D9:
6243         case RENDERPATH_D3D10:
6244         case RENDERPATH_D3D11:
6245                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6246                 break;
6247         }
6248         // TODO: do boxfilter scale-down in shader?
6249         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6250         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6251         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6252
6253         // we now have a properly scaled bloom image
6254         if (!r_fb.bloomfbo[r_fb.bloomindex])
6255         {
6256                 // copy it into the bloom texture
6257                 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);
6258                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6259         }
6260
6261         // multiply bloom image by itself as many times as desired
6262         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6263         {
6264                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6265                 r_fb.bloomindex ^= 1;
6266                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6267                 x *= 2;
6268                 r = bound(0, r_bloom_colorexponent.value / x, 1);
6269                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
6270                 GL_Color(r,r,r,1);
6271                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6272                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6273                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6274                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6275
6276                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6277                 {
6278                         // copy the darkened image to a texture
6279                         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);
6280                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6281                 }
6282         }
6283
6284         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6285         brighten = r_bloom_brighten.value;
6286         brighten = sqrt(brighten);
6287         if(range >= 1)
6288                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6289
6290         for (dir = 0;dir < 2;dir++)
6291         {
6292                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6293                 r_fb.bloomindex ^= 1;
6294                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6295                 // blend on at multiple vertical offsets to achieve a vertical blur
6296                 // TODO: do offset blends using GLSL
6297                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6298                 GL_BlendFunc(GL_ONE, GL_ZERO);
6299                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6300                 for (x = -range;x <= range;x++)
6301                 {
6302                         if (!dir){xoffset = 0;yoffset = x;}
6303                         else {xoffset = x;yoffset = 0;}
6304                         xoffset /= (float)r_fb.bloomtexturewidth;
6305                         yoffset /= (float)r_fb.bloomtextureheight;
6306                         // compute a texcoord array with the specified x and y offset
6307                         r_fb.offsettexcoord2f[0] = xoffset+0;
6308                         r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6309                         r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6310                         r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6311                         r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6312                         r_fb.offsettexcoord2f[5] = yoffset+0;
6313                         r_fb.offsettexcoord2f[6] = xoffset+0;
6314                         r_fb.offsettexcoord2f[7] = yoffset+0;
6315                         // this r value looks like a 'dot' particle, fading sharply to
6316                         // black at the edges
6317                         // (probably not realistic but looks good enough)
6318                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6319                         //r = brighten/(range*2+1);
6320                         r = brighten / (range * 2 + 1);
6321                         if(range >= 1)
6322                                 r *= (1 - x*x/(float)(range*range));
6323                         GL_Color(r, r, r, 1);
6324                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6325                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6326                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6327                         GL_BlendFunc(GL_ONE, GL_ONE);
6328                 }
6329
6330                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6331                 {
6332                         // copy the vertically or horizontally blurred bloom view to a texture
6333                         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);
6334                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6335                 }
6336         }
6337 }
6338
6339 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6340 {
6341         unsigned int permutation;
6342         float uservecs[4][4];
6343
6344         switch (vid.renderpath)
6345         {
6346         case RENDERPATH_GL20:
6347         case RENDERPATH_D3D9:
6348         case RENDERPATH_D3D10:
6349         case RENDERPATH_D3D11:
6350         case RENDERPATH_SOFT:
6351         case RENDERPATH_GLES2:
6352                 permutation =
6353                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6354                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6355                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6356                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6357                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6358
6359                 if (r_fb.colortexture)
6360                 {
6361                         if (!r_fb.fbo)
6362                         {
6363                                 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);
6364                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6365                         }
6366
6367                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6368                         {
6369                                 // declare variables
6370                                 float blur_factor, blur_mouseaccel, blur_velocity;
6371                                 static float blur_average; 
6372                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6373
6374                                 // set a goal for the factoring
6375                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6376                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6377                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6378                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6379                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6380                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6381
6382                                 // from the goal, pick an averaged value between goal and last value
6383                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6384                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6385
6386                                 // enforce minimum amount of blur 
6387                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6388
6389                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6390
6391                                 // calculate values into a standard alpha
6392                                 cl.motionbluralpha = 1 - exp(-
6393                                                 (
6394                                                  (r_motionblur.value * blur_factor / 80)
6395                                                  +
6396                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6397                                                 )
6398                                                 /
6399                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6400                                           );
6401
6402                                 // randomization for the blur value to combat persistent ghosting
6403                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6404                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6405
6406                                 // apply the blur
6407                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6408                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6409                                 {
6410                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6411                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6412                                         switch(vid.renderpath)
6413                                         {
6414                                         case RENDERPATH_GL11:
6415                                         case RENDERPATH_GL13:
6416                                         case RENDERPATH_GL20:
6417                                         case RENDERPATH_GLES1:
6418                                         case RENDERPATH_GLES2:
6419                                         case RENDERPATH_SOFT:
6420                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6421                                                 break;
6422                                         case RENDERPATH_D3D9:
6423                                         case RENDERPATH_D3D10:
6424                                         case RENDERPATH_D3D11:
6425                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6426                                                 break;
6427                                         }
6428                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6429                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6430                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6431                                 }
6432
6433                                 // updates old view angles for next pass
6434                                 VectorCopy(cl.viewangles, blur_oldangles);
6435
6436                                 // copy view into the ghost texture
6437                                 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);
6438                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6439                                 r_fb.ghosttexture_valid = true;
6440                         }
6441                 }
6442                 else
6443                 {
6444                         // no r_fb.colortexture means we're rendering to the real fb
6445                         // we may still have to do view tint...
6446                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6447                         {
6448                                 // apply a color tint to the whole view
6449                                 R_ResetViewRendering2D(0, NULL, NULL);
6450                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6451                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6452                                 R_SetupShader_Generic_NoTexture(false, true);
6453                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6454                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6455                         }
6456                         break; // no screen processing, no bloom, skip it
6457                 }
6458
6459                 if (r_fb.bloomtexture[0])
6460                 {
6461                         // make the bloom texture
6462                         R_Bloom_MakeTexture();
6463                 }
6464
6465 #if _MSC_VER >= 1400
6466 #define sscanf sscanf_s
6467 #endif
6468                 memset(uservecs, 0, sizeof(uservecs));
6469                 if (r_glsl_postprocess_uservec1_enable.integer)
6470                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6471                 if (r_glsl_postprocess_uservec2_enable.integer)
6472                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6473                 if (r_glsl_postprocess_uservec3_enable.integer)
6474                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6475                 if (r_glsl_postprocess_uservec4_enable.integer)
6476                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6477
6478                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6479                 GL_Color(1, 1, 1, 1);
6480                 GL_BlendFunc(GL_ONE, GL_ZERO);
6481
6482                 switch(vid.renderpath)
6483                 {
6484                 case RENDERPATH_GL20:
6485                 case RENDERPATH_GLES2:
6486                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6487                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6488                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6489                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6490                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6491                         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]);
6492                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6493                         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]);
6494                         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]);
6495                         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]);
6496                         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]);
6497                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6498                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6499                         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);
6500                         break;
6501                 case RENDERPATH_D3D9:
6502 #ifdef SUPPORTD3D
6503                         // 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...
6504                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6505                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6506                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6507                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6508                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6509                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6510                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6511                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6512                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6513                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6514                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6515                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6516                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6517                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6518 #endif
6519                         break;
6520                 case RENDERPATH_D3D10:
6521                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6522                         break;
6523                 case RENDERPATH_D3D11:
6524                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6525                         break;
6526                 case RENDERPATH_SOFT:
6527                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6528                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6529                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6530                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6531                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6532                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6533                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6534                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6535                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6536                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6537                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6538                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6539                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6540                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6541                         break;
6542                 default:
6543                         break;
6544                 }
6545                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6546                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6547                 break;
6548         case RENDERPATH_GL11:
6549         case RENDERPATH_GL13:
6550         case RENDERPATH_GLES1:
6551                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6552                 {
6553                         // apply a color tint to the whole view
6554                         R_ResetViewRendering2D(0, NULL, NULL);
6555                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6556                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6557                         R_SetupShader_Generic_NoTexture(false, true);
6558                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6559                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6560                 }
6561                 break;
6562         }
6563 }
6564
6565 matrix4x4_t r_waterscrollmatrix;
6566
6567 void R_UpdateFog(void)
6568 {
6569         // Nehahra fog
6570         if (gamemode == GAME_NEHAHRA)
6571         {
6572                 if (gl_fogenable.integer)
6573                 {
6574                         r_refdef.oldgl_fogenable = true;
6575                         r_refdef.fog_density = gl_fogdensity.value;
6576                         r_refdef.fog_red = gl_fogred.value;
6577                         r_refdef.fog_green = gl_foggreen.value;
6578                         r_refdef.fog_blue = gl_fogblue.value;
6579                         r_refdef.fog_alpha = 1;
6580                         r_refdef.fog_start = 0;
6581                         r_refdef.fog_end = gl_skyclip.value;
6582                         r_refdef.fog_height = 1<<30;
6583                         r_refdef.fog_fadedepth = 128;
6584                 }
6585                 else if (r_refdef.oldgl_fogenable)
6586                 {
6587                         r_refdef.oldgl_fogenable = false;
6588                         r_refdef.fog_density = 0;
6589                         r_refdef.fog_red = 0;
6590                         r_refdef.fog_green = 0;
6591                         r_refdef.fog_blue = 0;
6592                         r_refdef.fog_alpha = 0;
6593                         r_refdef.fog_start = 0;
6594                         r_refdef.fog_end = 0;
6595                         r_refdef.fog_height = 1<<30;
6596                         r_refdef.fog_fadedepth = 128;
6597                 }
6598         }
6599
6600         // fog parms
6601         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6602         r_refdef.fog_start = max(0, r_refdef.fog_start);
6603         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6604
6605         if (r_refdef.fog_density && r_drawfog.integer)
6606         {
6607                 r_refdef.fogenabled = true;
6608                 // this is the point where the fog reaches 0.9986 alpha, which we
6609                 // consider a good enough cutoff point for the texture
6610                 // (0.9986 * 256 == 255.6)
6611                 if (r_fog_exp2.integer)
6612                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6613                 else
6614                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6615                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6616                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6617                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6618                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6619                         R_BuildFogHeightTexture();
6620                 // fog color was already set
6621                 // update the fog texture
6622                 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)
6623                         R_BuildFogTexture();
6624                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6625                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6626         }
6627         else
6628                 r_refdef.fogenabled = false;
6629
6630         // fog color
6631         if (r_refdef.fog_density)
6632         {
6633                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6634                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6635                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6636
6637                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6638                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6639                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6640                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6641
6642                 {
6643                         vec3_t fogvec;
6644                         VectorCopy(r_refdef.fogcolor, fogvec);
6645                         //   color.rgb *= ContrastBoost * SceneBrightness;
6646                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6647                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6648                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6649                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6650                 }
6651         }
6652 }
6653
6654 void R_UpdateVariables(void)
6655 {
6656         R_Textures_Frame();
6657
6658         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6659
6660         r_refdef.farclip = r_farclip_base.value;
6661         if (r_refdef.scene.worldmodel)
6662                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6663         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6664
6665         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6666                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6667         r_refdef.polygonfactor = 0;
6668         r_refdef.polygonoffset = 0;
6669         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6670         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6671
6672         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6673         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6674         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6675         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6676         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6677         if (FAKELIGHT_ENABLED)
6678         {
6679                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6680         }
6681         if (r_showsurfaces.integer)
6682         {
6683                 r_refdef.scene.rtworld = false;
6684                 r_refdef.scene.rtworldshadows = false;
6685                 r_refdef.scene.rtdlight = false;
6686                 r_refdef.scene.rtdlightshadows = false;
6687                 r_refdef.lightmapintensity = 0;
6688         }
6689
6690         switch(vid.renderpath)
6691         {
6692         case RENDERPATH_GL20:
6693         case RENDERPATH_D3D9:
6694         case RENDERPATH_D3D10:
6695         case RENDERPATH_D3D11:
6696         case RENDERPATH_SOFT:
6697         case RENDERPATH_GLES2:
6698                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6699                 {
6700                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6701                         {
6702                                 // build GLSL gamma texture
6703 #define RAMPWIDTH 256
6704                                 unsigned short ramp[RAMPWIDTH * 3];
6705                                 unsigned char rampbgr[RAMPWIDTH][4];
6706                                 int i;
6707
6708                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6709
6710                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6711                                 for(i = 0; i < RAMPWIDTH; ++i)
6712                                 {
6713                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6714                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6715                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6716                                         rampbgr[i][3] = 0;
6717                                 }
6718                                 if (r_texture_gammaramps)
6719                                 {
6720                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6721                                 }
6722                                 else
6723                                 {
6724                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6725                                 }
6726                         }
6727                 }
6728                 else
6729                 {
6730                         // remove GLSL gamma texture
6731                 }
6732                 break;
6733         case RENDERPATH_GL11:
6734         case RENDERPATH_GL13:
6735         case RENDERPATH_GLES1:
6736                 break;
6737         }
6738 }
6739
6740 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6741 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6742 /*
6743 ================
6744 R_SelectScene
6745 ================
6746 */
6747 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6748         if( scenetype != r_currentscenetype ) {
6749                 // store the old scenetype
6750                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6751                 r_currentscenetype = scenetype;
6752                 // move in the new scene
6753                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6754         }
6755 }
6756
6757 /*
6758 ================
6759 R_GetScenePointer
6760 ================
6761 */
6762 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6763 {
6764         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6765         if( scenetype == r_currentscenetype ) {
6766                 return &r_refdef.scene;
6767         } else {
6768                 return &r_scenes_store[ scenetype ];
6769         }
6770 }
6771
6772 static int R_SortEntities_Compare(const void *ap, const void *bp)
6773 {
6774         const entity_render_t *a = *(const entity_render_t **)ap;
6775         const entity_render_t *b = *(const entity_render_t **)bp;
6776
6777         // 1. compare model
6778         if(a->model < b->model)
6779                 return -1;
6780         if(a->model > b->model)
6781                 return +1;
6782
6783         // 2. compare skin
6784         // TODO possibly calculate the REAL skinnum here first using
6785         // skinscenes?
6786         if(a->skinnum < b->skinnum)
6787                 return -1;
6788         if(a->skinnum > b->skinnum)
6789                 return +1;
6790
6791         // everything we compared is equal
6792         return 0;
6793 }
6794 static void R_SortEntities(void)
6795 {
6796         // below or equal 2 ents, sorting never gains anything
6797         if(r_refdef.scene.numentities <= 2)
6798                 return;
6799         // sort
6800         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6801 }
6802
6803 /*
6804 ================
6805 R_RenderView
6806 ================
6807 */
6808 int dpsoftrast_test;
6809 extern cvar_t r_shadow_bouncegrid;
6810 void R_RenderView(void)
6811 {
6812         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6813         int fbo;
6814         rtexture_t *depthtexture;
6815         rtexture_t *colortexture;
6816
6817         dpsoftrast_test = r_test.integer;
6818
6819         if (r_timereport_active)
6820                 R_TimeReport("start");
6821         r_textureframe++; // used only by R_GetCurrentTexture
6822         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6823
6824         if(R_CompileShader_CheckStaticParms())
6825                 R_GLSL_Restart_f();
6826
6827         if (!r_drawentities.integer)
6828                 r_refdef.scene.numentities = 0;
6829         else if (r_sortentities.integer)
6830                 R_SortEntities();
6831
6832         R_AnimCache_ClearCache();
6833         R_FrameData_NewFrame();
6834
6835         /* adjust for stereo display */
6836         if(R_Stereo_Active())
6837         {
6838                 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);
6839                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6840         }
6841
6842         if (r_refdef.view.isoverlay)
6843         {
6844                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6845                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6846                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6847                 R_TimeReport("depthclear");
6848
6849                 r_refdef.view.showdebug = false;
6850
6851                 r_fb.water.enabled = false;
6852                 r_fb.water.numwaterplanes = 0;
6853
6854                 R_RenderScene(0, NULL, NULL);
6855
6856                 r_refdef.view.matrix = originalmatrix;
6857
6858                 CHECKGLERROR
6859                 return;
6860         }
6861
6862         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6863         {
6864                 r_refdef.view.matrix = originalmatrix;
6865                 return;
6866         }
6867
6868         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6869
6870         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6871                 // in sRGB fallback, behave similar to true sRGB: convert this
6872                 // value from linear to sRGB
6873                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6874
6875         R_RenderView_UpdateViewVectors();
6876
6877         R_Shadow_UpdateWorldLightSelection();
6878
6879         R_Bloom_StartFrame();
6880         R_Water_StartFrame();
6881
6882         // now we probably have an fbo to render into
6883         fbo = r_fb.fbo;
6884         depthtexture = r_fb.depthtexture;
6885         colortexture = r_fb.colortexture;
6886
6887         CHECKGLERROR
6888         if (r_timereport_active)
6889                 R_TimeReport("viewsetup");
6890
6891         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6892
6893         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6894         {
6895                 R_ClearScreen(r_refdef.fogenabled);
6896                 if (r_timereport_active)
6897                         R_TimeReport("viewclear");
6898         }
6899         r_refdef.view.clear = true;
6900
6901         r_refdef.view.showdebug = true;
6902
6903         R_View_Update();
6904         if (r_timereport_active)
6905                 R_TimeReport("visibility");
6906
6907         R_Shadow_UpdateBounceGridTexture();
6908         if (r_timereport_active && r_shadow_bouncegrid.integer)
6909                 R_TimeReport("bouncegrid");
6910
6911         r_fb.water.numwaterplanes = 0;
6912         if (r_fb.water.enabled)
6913                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6914
6915         R_RenderScene(fbo, depthtexture, colortexture);
6916         r_fb.water.numwaterplanes = 0;
6917
6918         R_BlendView(fbo, depthtexture, colortexture);
6919         if (r_timereport_active)
6920                 R_TimeReport("blendview");
6921
6922         GL_Scissor(0, 0, vid.width, vid.height);
6923         GL_ScissorTest(false);
6924
6925         r_refdef.view.matrix = originalmatrix;
6926
6927         CHECKGLERROR
6928 }
6929
6930 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6931 {
6932         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6933         {
6934                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6935                 if (r_timereport_active)
6936                         R_TimeReport("waterworld");
6937         }
6938
6939         // don't let sound skip if going slow
6940         if (r_refdef.scene.extraupdate)
6941                 S_ExtraUpdate ();
6942
6943         R_DrawModelsAddWaterPlanes();
6944         if (r_timereport_active)
6945                 R_TimeReport("watermodels");
6946
6947         if (r_fb.water.numwaterplanes)
6948         {
6949                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6950                 if (r_timereport_active)
6951                         R_TimeReport("waterscenes");
6952         }
6953 }
6954
6955 extern cvar_t cl_locs_show;
6956 static void R_DrawLocs(void);
6957 static void R_DrawEntityBBoxes(void);
6958 static void R_DrawModelDecals(void);
6959 extern cvar_t cl_decals_newsystem;
6960 extern qboolean r_shadow_usingdeferredprepass;
6961 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6962 {
6963         qboolean shadowmapping = false;
6964
6965         if (r_timereport_active)
6966                 R_TimeReport("beginscene");
6967
6968         r_refdef.stats.renders++;
6969
6970         R_UpdateFog();
6971
6972         // don't let sound skip if going slow
6973         if (r_refdef.scene.extraupdate)
6974                 S_ExtraUpdate ();
6975
6976         R_MeshQueue_BeginScene();
6977
6978         R_SkyStartFrame();
6979
6980         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);
6981
6982         if (r_timereport_active)
6983                 R_TimeReport("skystartframe");
6984
6985         if (cl.csqc_vidvars.drawworld)
6986         {
6987                 // don't let sound skip if going slow
6988                 if (r_refdef.scene.extraupdate)
6989                         S_ExtraUpdate ();
6990
6991                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
6992                 {
6993                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
6994                         if (r_timereport_active)
6995                                 R_TimeReport("worldsky");
6996                 }
6997
6998                 if (R_DrawBrushModelsSky() && r_timereport_active)
6999                         R_TimeReport("bmodelsky");
7000
7001                 if (skyrendermasked && skyrenderlater)
7002                 {
7003                         // we have to force off the water clipping plane while rendering sky
7004                         R_SetupView(false, fbo, depthtexture, colortexture);
7005                         R_Sky();
7006                         R_SetupView(true, fbo, depthtexture, colortexture);
7007                         if (r_timereport_active)
7008                                 R_TimeReport("sky");
7009                 }
7010         }
7011
7012         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7013         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7014                 R_Shadow_PrepareModelShadows();
7015         if (r_timereport_active)
7016                 R_TimeReport("preparelights");
7017
7018         if (R_Shadow_ShadowMappingEnabled())
7019                 shadowmapping = true;
7020
7021         if (r_shadow_usingdeferredprepass)
7022                 R_Shadow_DrawPrepass();
7023
7024         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7025         {
7026                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7027                 if (r_timereport_active)
7028                         R_TimeReport("worlddepth");
7029         }
7030         if (r_depthfirst.integer >= 2)
7031         {
7032                 R_DrawModelsDepth();
7033                 if (r_timereport_active)
7034                         R_TimeReport("modeldepth");
7035         }
7036
7037         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7038         {
7039                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7040                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7041                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7042                 // don't let sound skip if going slow
7043                 if (r_refdef.scene.extraupdate)
7044                         S_ExtraUpdate ();
7045         }
7046
7047         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7048         {
7049                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7050                 if (r_timereport_active)
7051                         R_TimeReport("world");
7052         }
7053
7054         // don't let sound skip if going slow
7055         if (r_refdef.scene.extraupdate)
7056                 S_ExtraUpdate ();
7057
7058         R_DrawModels();
7059         if (r_timereport_active)
7060                 R_TimeReport("models");
7061
7062         // don't let sound skip if going slow
7063         if (r_refdef.scene.extraupdate)
7064                 S_ExtraUpdate ();
7065
7066         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7067         {
7068                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7069                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7070                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7071                 // don't let sound skip if going slow
7072                 if (r_refdef.scene.extraupdate)
7073                         S_ExtraUpdate ();
7074         }
7075
7076         if (!r_shadow_usingdeferredprepass)
7077         {
7078                 R_Shadow_DrawLights();
7079                 if (r_timereport_active)
7080                         R_TimeReport("rtlights");
7081         }
7082
7083         // don't let sound skip if going slow
7084         if (r_refdef.scene.extraupdate)
7085                 S_ExtraUpdate ();
7086
7087         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7088         {
7089                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7090                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7091                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7092                 // don't let sound skip if going slow
7093                 if (r_refdef.scene.extraupdate)
7094                         S_ExtraUpdate ();
7095         }
7096
7097         if (cl.csqc_vidvars.drawworld)
7098         {
7099                 if (cl_decals_newsystem.integer)
7100                 {
7101                         R_DrawModelDecals();
7102                         if (r_timereport_active)
7103                                 R_TimeReport("modeldecals");
7104                 }
7105                 else
7106                 {
7107                         R_DrawDecals();
7108                         if (r_timereport_active)
7109                                 R_TimeReport("decals");
7110                 }
7111
7112                 R_DrawParticles();
7113                 if (r_timereport_active)
7114                         R_TimeReport("particles");
7115
7116                 R_DrawExplosions();
7117                 if (r_timereport_active)
7118                         R_TimeReport("explosions");
7119
7120                 R_DrawLightningBeams();
7121                 if (r_timereport_active)
7122                         R_TimeReport("lightning");
7123         }
7124
7125         if (cl.csqc_loaded)
7126                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7127
7128         if (r_refdef.view.showdebug)
7129         {
7130                 if (cl_locs_show.integer)
7131                 {
7132                         R_DrawLocs();
7133                         if (r_timereport_active)
7134                                 R_TimeReport("showlocs");
7135                 }
7136
7137                 if (r_drawportals.integer)
7138                 {
7139                         R_DrawPortals();
7140                         if (r_timereport_active)
7141                                 R_TimeReport("portals");
7142                 }
7143
7144                 if (r_showbboxes.value > 0)
7145                 {
7146                         R_DrawEntityBBoxes();
7147                         if (r_timereport_active)
7148                                 R_TimeReport("bboxes");
7149                 }
7150         }
7151
7152         if (r_transparent.integer)
7153         {
7154                 R_MeshQueue_RenderTransparent();
7155                 if (r_timereport_active)
7156                         R_TimeReport("drawtrans");
7157         }
7158
7159         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))
7160         {
7161                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7162                 if (r_timereport_active)
7163                         R_TimeReport("worlddebug");
7164                 R_DrawModelsDebug();
7165                 if (r_timereport_active)
7166                         R_TimeReport("modeldebug");
7167         }
7168
7169         if (cl.csqc_vidvars.drawworld)
7170         {
7171                 R_Shadow_DrawCoronas();
7172                 if (r_timereport_active)
7173                         R_TimeReport("coronas");
7174         }
7175
7176 #if 0
7177         {
7178                 GL_DepthTest(false);
7179                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7180                 GL_Color(1, 1, 1, 1);
7181                 qglBegin(GL_POLYGON);
7182                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7183                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7184                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7185                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7186                 qglEnd();
7187                 qglBegin(GL_POLYGON);
7188                 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]);
7189                 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]);
7190                 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]);
7191                 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]);
7192                 qglEnd();
7193                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7194         }
7195 #endif
7196
7197         // don't let sound skip if going slow
7198         if (r_refdef.scene.extraupdate)
7199                 S_ExtraUpdate ();
7200 }
7201
7202 static const unsigned short bboxelements[36] =
7203 {
7204         5, 1, 3, 5, 3, 7,
7205         6, 2, 0, 6, 0, 4,
7206         7, 3, 2, 7, 2, 6,
7207         4, 0, 1, 4, 1, 5,
7208         4, 5, 7, 4, 7, 6,
7209         1, 0, 2, 1, 2, 3,
7210 };
7211
7212 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7213 {
7214         int i;
7215         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7216
7217         RSurf_ActiveWorldEntity();
7218
7219         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7220         GL_DepthMask(false);
7221         GL_DepthRange(0, 1);
7222         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7223 //      R_Mesh_ResetTextureState();
7224
7225         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7226         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7227         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7228         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7229         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7230         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7231         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7232         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7233         R_FillColors(color4f, 8, cr, cg, cb, ca);
7234         if (r_refdef.fogenabled)
7235         {
7236                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7237                 {
7238                         f1 = RSurf_FogVertex(v);
7239                         f2 = 1 - f1;
7240                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7241                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7242                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7243                 }
7244         }
7245         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7246         R_Mesh_ResetTextureState();
7247         R_SetupShader_Generic_NoTexture(false, false);
7248         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7249 }
7250
7251 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7252 {
7253         prvm_prog_t *prog = SVVM_prog;
7254         int i;
7255         float color[4];
7256         prvm_edict_t *edict;
7257
7258         // this function draws bounding boxes of server entities
7259         if (!sv.active)
7260                 return;
7261
7262         GL_CullFace(GL_NONE);
7263         R_SetupShader_Generic_NoTexture(false, false);
7264
7265         for (i = 0;i < numsurfaces;i++)
7266         {
7267                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7268                 switch ((int)PRVM_serveredictfloat(edict, solid))
7269                 {
7270                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7271                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7272                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7273                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7274                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7275                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7276                 }
7277                 color[3] *= r_showbboxes.value;
7278                 color[3] = bound(0, color[3], 1);
7279                 GL_DepthTest(!r_showdisabledepthtest.integer);
7280                 GL_CullFace(r_refdef.view.cullface_front);
7281                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7282         }
7283 }
7284
7285 static void R_DrawEntityBBoxes(void)
7286 {
7287         int i;
7288         prvm_edict_t *edict;
7289         vec3_t center;
7290         prvm_prog_t *prog = SVVM_prog;
7291
7292         // this function draws bounding boxes of server entities
7293         if (!sv.active)
7294                 return;
7295
7296         for (i = 0;i < prog->num_edicts;i++)
7297         {
7298                 edict = PRVM_EDICT_NUM(i);
7299                 if (edict->priv.server->free)
7300                         continue;
7301                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7302                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7303                         continue;
7304                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7305                         continue;
7306                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7307                 R_MeshQueue_AddTransparent(center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7308         }
7309 }
7310
7311 static const int nomodelelement3i[24] =
7312 {
7313         5, 2, 0,
7314         5, 1, 2,
7315         5, 0, 3,
7316         5, 3, 1,
7317         0, 2, 4,
7318         2, 1, 4,
7319         3, 0, 4,
7320         1, 3, 4
7321 };
7322
7323 static const unsigned short nomodelelement3s[24] =
7324 {
7325         5, 2, 0,
7326         5, 1, 2,
7327         5, 0, 3,
7328         5, 3, 1,
7329         0, 2, 4,
7330         2, 1, 4,
7331         3, 0, 4,
7332         1, 3, 4
7333 };
7334
7335 static const float nomodelvertex3f[6*3] =
7336 {
7337         -16,   0,   0,
7338          16,   0,   0,
7339           0, -16,   0,
7340           0,  16,   0,
7341           0,   0, -16,
7342           0,   0,  16
7343 };
7344
7345 static const float nomodelcolor4f[6*4] =
7346 {
7347         0.0f, 0.0f, 0.5f, 1.0f,
7348         0.0f, 0.0f, 0.5f, 1.0f,
7349         0.0f, 0.5f, 0.0f, 1.0f,
7350         0.0f, 0.5f, 0.0f, 1.0f,
7351         0.5f, 0.0f, 0.0f, 1.0f,
7352         0.5f, 0.0f, 0.0f, 1.0f
7353 };
7354
7355 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7356 {
7357         int i;
7358         float f1, f2, *c;
7359         float color4f[6*4];
7360
7361         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);
7362
7363         // this is only called once per entity so numsurfaces is always 1, and
7364         // surfacelist is always {0}, so this code does not handle batches
7365
7366         if (rsurface.ent_flags & RENDER_ADDITIVE)
7367         {
7368                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7369                 GL_DepthMask(false);
7370         }
7371         else if (rsurface.colormod[3] < 1)
7372         {
7373                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7374                 GL_DepthMask(false);
7375         }
7376         else
7377         {
7378                 GL_BlendFunc(GL_ONE, GL_ZERO);
7379                 GL_DepthMask(true);
7380         }
7381         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7382         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7383         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7384         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7385         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7386         for (i = 0, c = color4f;i < 6;i++, c += 4)
7387         {
7388                 c[0] *= rsurface.colormod[0];
7389                 c[1] *= rsurface.colormod[1];
7390                 c[2] *= rsurface.colormod[2];
7391                 c[3] *= rsurface.colormod[3];
7392         }
7393         if (r_refdef.fogenabled)
7394         {
7395                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7396                 {
7397                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7398                         f2 = 1 - f1;
7399                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7400                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7401                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7402                 }
7403         }
7404 //      R_Mesh_ResetTextureState();
7405         R_SetupShader_Generic_NoTexture(false, false);
7406         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7407         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7408 }
7409
7410 void R_DrawNoModel(entity_render_t *ent)
7411 {
7412         vec3_t org;
7413         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7414         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7415                 R_MeshQueue_AddTransparent(ent->flags & RENDER_NODEPTHTEST ? r_refdef.view.origin : org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7416         else
7417                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7418 }
7419
7420 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7421 {
7422         vec3_t right1, right2, diff, normal;
7423
7424         VectorSubtract (org2, org1, normal);
7425
7426         // calculate 'right' vector for start
7427         VectorSubtract (r_refdef.view.origin, org1, diff);
7428         CrossProduct (normal, diff, right1);
7429         VectorNormalize (right1);
7430
7431         // calculate 'right' vector for end
7432         VectorSubtract (r_refdef.view.origin, org2, diff);
7433         CrossProduct (normal, diff, right2);
7434         VectorNormalize (right2);
7435
7436         vert[ 0] = org1[0] + width * right1[0];
7437         vert[ 1] = org1[1] + width * right1[1];
7438         vert[ 2] = org1[2] + width * right1[2];
7439         vert[ 3] = org1[0] - width * right1[0];
7440         vert[ 4] = org1[1] - width * right1[1];
7441         vert[ 5] = org1[2] - width * right1[2];
7442         vert[ 6] = org2[0] - width * right2[0];
7443         vert[ 7] = org2[1] - width * right2[1];
7444         vert[ 8] = org2[2] - width * right2[2];
7445         vert[ 9] = org2[0] + width * right2[0];
7446         vert[10] = org2[1] + width * right2[1];
7447         vert[11] = org2[2] + width * right2[2];
7448 }
7449
7450 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)
7451 {
7452         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7453         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7454         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7455         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7456         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7457         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7458         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7459         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7460         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7461         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7462         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7463         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7464 }
7465
7466 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7467 {
7468         int i;
7469         float *vertex3f;
7470         float v[3];
7471         VectorSet(v, x, y, z);
7472         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7473                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7474                         break;
7475         if (i == mesh->numvertices)
7476         {
7477                 if (mesh->numvertices < mesh->maxvertices)
7478                 {
7479                         VectorCopy(v, vertex3f);
7480                         mesh->numvertices++;
7481                 }
7482                 return mesh->numvertices;
7483         }
7484         else
7485                 return i;
7486 }
7487
7488 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7489 {
7490         int i;
7491         int *e, element[3];
7492         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7493         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7494         e = mesh->element3i + mesh->numtriangles * 3;
7495         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7496         {
7497                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7498                 if (mesh->numtriangles < mesh->maxtriangles)
7499                 {
7500                         *e++ = element[0];
7501                         *e++ = element[1];
7502                         *e++ = element[2];
7503                         mesh->numtriangles++;
7504                 }
7505                 element[1] = element[2];
7506         }
7507 }
7508
7509 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7510 {
7511         int i;
7512         int *e, element[3];
7513         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7514         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7515         e = mesh->element3i + mesh->numtriangles * 3;
7516         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7517         {
7518                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7519                 if (mesh->numtriangles < mesh->maxtriangles)
7520                 {
7521                         *e++ = element[0];
7522                         *e++ = element[1];
7523                         *e++ = element[2];
7524                         mesh->numtriangles++;
7525                 }
7526                 element[1] = element[2];
7527         }
7528 }
7529
7530 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7531 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7532 {
7533         int planenum, planenum2;
7534         int w;
7535         int tempnumpoints;
7536         mplane_t *plane, *plane2;
7537         double maxdist;
7538         double temppoints[2][256*3];
7539         // figure out how large a bounding box we need to properly compute this brush
7540         maxdist = 0;
7541         for (w = 0;w < numplanes;w++)
7542                 maxdist = max(maxdist, fabs(planes[w].dist));
7543         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7544         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7545         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7546         {
7547                 w = 0;
7548                 tempnumpoints = 4;
7549                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7550                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7551                 {
7552                         if (planenum2 == planenum)
7553                                 continue;
7554                         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);
7555                         w = !w;
7556                 }
7557                 if (tempnumpoints < 3)
7558                         continue;
7559                 // generate elements forming a triangle fan for this polygon
7560                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7561         }
7562 }
7563
7564 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)
7565 {
7566         texturelayer_t *layer;
7567         layer = t->currentlayers + t->currentnumlayers++;
7568         layer->type = type;
7569         layer->depthmask = depthmask;
7570         layer->blendfunc1 = blendfunc1;
7571         layer->blendfunc2 = blendfunc2;
7572         layer->texture = texture;
7573         layer->texmatrix = *matrix;
7574         layer->color[0] = r;
7575         layer->color[1] = g;
7576         layer->color[2] = b;
7577         layer->color[3] = a;
7578 }
7579
7580 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7581 {
7582         if(parms[0] == 0 && parms[1] == 0)
7583                 return false;
7584         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7585                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7586                         return false;
7587         return true;
7588 }
7589
7590 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7591 {
7592         double index, f;
7593         index = parms[2] + rsurface.shadertime * parms[3];
7594         index -= floor(index);
7595         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7596         {
7597         default:
7598         case Q3WAVEFUNC_NONE:
7599         case Q3WAVEFUNC_NOISE:
7600         case Q3WAVEFUNC_COUNT:
7601                 f = 0;
7602                 break;
7603         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7604         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7605         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7606         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7607         case Q3WAVEFUNC_TRIANGLE:
7608                 index *= 4;
7609                 f = index - floor(index);
7610                 if (index < 1)
7611                 {
7612                         // f = f;
7613                 }
7614                 else if (index < 2)
7615                         f = 1 - f;
7616                 else if (index < 3)
7617                         f = -f;
7618                 else
7619                         f = -(1 - f);
7620                 break;
7621         }
7622         f = parms[0] + parms[1] * f;
7623         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7624                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7625         return (float) f;
7626 }
7627
7628 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7629 {
7630         int w, h, idx;
7631         double f;
7632         double offsetd[2];
7633         float tcmat[12];
7634         matrix4x4_t matrix, temp;
7635         switch(tcmod->tcmod)
7636         {
7637                 case Q3TCMOD_COUNT:
7638                 case Q3TCMOD_NONE:
7639                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7640                                 matrix = r_waterscrollmatrix;
7641                         else
7642                                 matrix = identitymatrix;
7643                         break;
7644                 case Q3TCMOD_ENTITYTRANSLATE:
7645                         // this is used in Q3 to allow the gamecode to control texcoord
7646                         // scrolling on the entity, which is not supported in darkplaces yet.
7647                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7648                         break;
7649                 case Q3TCMOD_ROTATE:
7650                         f = tcmod->parms[0] * rsurface.shadertime;
7651                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7652                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7653                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7654                         break;
7655                 case Q3TCMOD_SCALE:
7656                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7657                         break;
7658                 case Q3TCMOD_SCROLL:
7659                         // extra care is needed because of precision breakdown with large values of time
7660                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7661                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7662                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7663                         break;
7664                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7665                         w = (int) tcmod->parms[0];
7666                         h = (int) tcmod->parms[1];
7667                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7668                         f = f - floor(f);
7669                         idx = (int) floor(f * w * h);
7670                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7671                         break;
7672                 case Q3TCMOD_STRETCH:
7673                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7674                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7675                         break;
7676                 case Q3TCMOD_TRANSFORM:
7677                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7678                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7679                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7680                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7681                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7682                         break;
7683                 case Q3TCMOD_TURBULENT:
7684                         // this is handled in the RSurf_PrepareVertices function
7685                         matrix = identitymatrix;
7686                         break;
7687         }
7688         temp = *texmatrix;
7689         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7690 }
7691
7692 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7693 {
7694         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7695         char name[MAX_QPATH];
7696         skinframe_t *skinframe;
7697         unsigned char pixels[296*194];
7698         strlcpy(cache->name, skinname, sizeof(cache->name));
7699         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7700         if (developer_loading.integer)
7701                 Con_Printf("loading %s\n", name);
7702         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7703         if (!skinframe || !skinframe->base)
7704         {
7705                 unsigned char *f;
7706                 fs_offset_t filesize;
7707                 skinframe = NULL;
7708                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7709                 if (f)
7710                 {
7711                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7712                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7713                         Mem_Free(f);
7714                 }
7715         }
7716         cache->skinframe = skinframe;
7717 }
7718
7719 texture_t *R_GetCurrentTexture(texture_t *t)
7720 {
7721         int i;
7722         const entity_render_t *ent = rsurface.entity;
7723         dp_model_t *model = ent->model;
7724         q3shaderinfo_layer_tcmod_t *tcmod;
7725
7726         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7727                 return t->currentframe;
7728         t->update_lastrenderframe = r_textureframe;
7729         t->update_lastrenderentity = (void *)ent;
7730
7731         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7732                 t->camera_entity = ent->entitynumber;
7733         else
7734                 t->camera_entity = 0;
7735
7736         // switch to an alternate material if this is a q1bsp animated material
7737         {
7738                 texture_t *texture = t;
7739                 int s = rsurface.ent_skinnum;
7740                 if ((unsigned int)s >= (unsigned int)model->numskins)
7741                         s = 0;
7742                 if (model->skinscenes)
7743                 {
7744                         if (model->skinscenes[s].framecount > 1)
7745                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7746                         else
7747                                 s = model->skinscenes[s].firstframe;
7748                 }
7749                 if (s > 0)
7750                         t = t + s * model->num_surfaces;
7751                 if (t->animated)
7752                 {
7753                         // use an alternate animation if the entity's frame is not 0,
7754                         // and only if the texture has an alternate animation
7755                         if (rsurface.ent_alttextures && t->anim_total[1])
7756                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7757                         else
7758                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7759                 }
7760                 texture->currentframe = t;
7761         }
7762
7763         // update currentskinframe to be a qw skin or animation frame
7764         if (rsurface.ent_qwskin >= 0)
7765         {
7766                 i = rsurface.ent_qwskin;
7767                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7768                 {
7769                         r_qwskincache_size = cl.maxclients;
7770                         if (r_qwskincache)
7771                                 Mem_Free(r_qwskincache);
7772                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7773                 }
7774                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7775                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7776                 t->currentskinframe = r_qwskincache[i].skinframe;
7777                 if (t->currentskinframe == NULL)
7778                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7779         }
7780         else if (t->numskinframes >= 2)
7781                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7782         if (t->backgroundnumskinframes >= 2)
7783                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7784
7785         t->currentmaterialflags = t->basematerialflags;
7786         t->currentalpha = rsurface.colormod[3];
7787         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7788                 t->currentalpha *= r_wateralpha.value;
7789         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7790                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7791         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7792                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7793         if (!(rsurface.ent_flags & RENDER_LIGHT))
7794                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7795         else if (FAKELIGHT_ENABLED)
7796         {
7797                 // no modellight if using fakelight for the map
7798         }
7799         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7800         {
7801                 // pick a model lighting mode
7802                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7803                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7804                 else
7805                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7806         }
7807         if (rsurface.ent_flags & RENDER_ADDITIVE)
7808                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7809         else if (t->currentalpha < 1)
7810                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7811         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7812         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7813                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7814         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7815                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7816         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7817                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7818         if (t->backgroundnumskinframes)
7819                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7820         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7821         {
7822                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7823                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7824         }
7825         else
7826                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7827         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7828         {
7829                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7830                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7831         }
7832         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7833                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7834
7835         // there is no tcmod
7836         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7837         {
7838                 t->currenttexmatrix = r_waterscrollmatrix;
7839                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7840         }
7841         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7842         {
7843                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7844                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7845         }
7846
7847         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7848                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7849         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7850                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7851
7852         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7853         if (t->currentskinframe->qpixels)
7854                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7855         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7856         if (!t->basetexture)
7857                 t->basetexture = r_texture_notexture;
7858         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7859         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7860         t->nmaptexture = t->currentskinframe->nmap;
7861         if (!t->nmaptexture)
7862                 t->nmaptexture = r_texture_blanknormalmap;
7863         t->glosstexture = r_texture_black;
7864         t->glowtexture = t->currentskinframe->glow;
7865         t->fogtexture = t->currentskinframe->fog;
7866         t->reflectmasktexture = t->currentskinframe->reflect;
7867         if (t->backgroundnumskinframes)
7868         {
7869                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7870                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7871                 t->backgroundglosstexture = r_texture_black;
7872                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7873                 if (!t->backgroundnmaptexture)
7874                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7875         }
7876         else
7877         {
7878                 t->backgroundbasetexture = r_texture_white;
7879                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7880                 t->backgroundglosstexture = r_texture_black;
7881                 t->backgroundglowtexture = NULL;
7882         }
7883         t->specularpower = r_shadow_glossexponent.value;
7884         // TODO: store reference values for these in the texture?
7885         t->specularscale = 0;
7886         if (r_shadow_gloss.integer > 0)
7887         {
7888                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7889                 {
7890                         if (r_shadow_glossintensity.value > 0)
7891                         {
7892                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7893                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7894                                 t->specularscale = r_shadow_glossintensity.value;
7895                         }
7896                 }
7897                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7898                 {
7899                         t->glosstexture = r_texture_white;
7900                         t->backgroundglosstexture = r_texture_white;
7901                         t->specularscale = r_shadow_gloss2intensity.value;
7902                         t->specularpower = r_shadow_gloss2exponent.value;
7903                 }
7904         }
7905         t->specularscale *= t->specularscalemod;
7906         t->specularpower *= t->specularpowermod;
7907         t->rtlightambient = 0;
7908
7909         // lightmaps mode looks bad with dlights using actual texturing, so turn
7910         // off the colormap and glossmap, but leave the normalmap on as it still
7911         // accurately represents the shading involved
7912         if (gl_lightmaps.integer)
7913         {
7914                 t->basetexture = r_texture_grey128;
7915                 t->pantstexture = r_texture_black;
7916                 t->shirttexture = r_texture_black;
7917                 t->nmaptexture = r_texture_blanknormalmap;
7918                 t->glosstexture = r_texture_black;
7919                 t->glowtexture = NULL;
7920                 t->fogtexture = NULL;
7921                 t->reflectmasktexture = NULL;
7922                 t->backgroundbasetexture = NULL;
7923                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7924                 t->backgroundglosstexture = r_texture_black;
7925                 t->backgroundglowtexture = NULL;
7926                 t->specularscale = 0;
7927                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7928         }
7929
7930         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7931         VectorClear(t->dlightcolor);
7932         t->currentnumlayers = 0;
7933         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7934         {
7935                 int blendfunc1, blendfunc2;
7936                 qboolean depthmask;
7937                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7938                 {
7939                         blendfunc1 = GL_SRC_ALPHA;
7940                         blendfunc2 = GL_ONE;
7941                 }
7942                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7943                 {
7944                         blendfunc1 = GL_SRC_ALPHA;
7945                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7946                 }
7947                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7948                 {
7949                         blendfunc1 = t->customblendfunc[0];
7950                         blendfunc2 = t->customblendfunc[1];
7951                 }
7952                 else
7953                 {
7954                         blendfunc1 = GL_ONE;
7955                         blendfunc2 = GL_ZERO;
7956                 }
7957                 // don't colormod evilblend textures
7958                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7959                         VectorSet(t->lightmapcolor, 1, 1, 1);
7960                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7961                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7962                 {
7963                         // fullbright is not affected by r_refdef.lightmapintensity
7964                         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]);
7965                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7966                                 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]);
7967                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7968                                 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]);
7969                 }
7970                 else
7971                 {
7972                         vec3_t ambientcolor;
7973                         float colorscale;
7974                         // set the color tint used for lights affecting this surface
7975                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7976                         colorscale = 2;
7977                         // q3bsp has no lightmap updates, so the lightstylevalue that
7978                         // would normally be baked into the lightmap must be
7979                         // applied to the color
7980                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7981                         if (model->type == mod_brushq3)
7982                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7983                         colorscale *= r_refdef.lightmapintensity;
7984                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7985                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7986                         // basic lit geometry
7987                         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]);
7988                         // add pants/shirt if needed
7989                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7990                                 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]);
7991                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7992                                 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]);
7993                         // now add ambient passes if needed
7994                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
7995                         {
7996                                 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]);
7997                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7998                                         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]);
7999                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8000                                         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]);
8001                         }
8002                 }
8003                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8004                         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]);
8005                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8006                 {
8007                         // if this is opaque use alpha blend which will darken the earlier
8008                         // passes cheaply.
8009                         //
8010                         // if this is an alpha blended material, all the earlier passes
8011                         // were darkened by fog already, so we only need to add the fog
8012                         // color ontop through the fog mask texture
8013                         //
8014                         // if this is an additive blended material, all the earlier passes
8015                         // were darkened by fog already, and we should not add fog color
8016                         // (because the background was not darkened, there is no fog color
8017                         // that was lost behind it).
8018                         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]);
8019                 }
8020         }
8021
8022         return t->currentframe;
8023 }
8024
8025 rsurfacestate_t rsurface;
8026
8027 void RSurf_ActiveWorldEntity(void)
8028 {
8029         dp_model_t *model = r_refdef.scene.worldmodel;
8030         //if (rsurface.entity == r_refdef.scene.worldentity)
8031         //      return;
8032         rsurface.entity = r_refdef.scene.worldentity;
8033         rsurface.skeleton = NULL;
8034         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8035         rsurface.ent_skinnum = 0;
8036         rsurface.ent_qwskin = -1;
8037         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8038         rsurface.shadertime = r_refdef.scene.time;
8039         rsurface.matrix = identitymatrix;
8040         rsurface.inversematrix = identitymatrix;
8041         rsurface.matrixscale = 1;
8042         rsurface.inversematrixscale = 1;
8043         R_EntityMatrix(&identitymatrix);
8044         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8045         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8046         rsurface.fograngerecip = r_refdef.fograngerecip;
8047         rsurface.fogheightfade = r_refdef.fogheightfade;
8048         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8049         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8050         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8051         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8052         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8053         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8054         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8055         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8056         rsurface.colormod[3] = 1;
8057         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);
8058         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8059         rsurface.frameblend[0].lerp = 1;
8060         rsurface.ent_alttextures = false;
8061         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8062         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8063         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8064         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8065         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8066         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8067         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8068         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8069         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8070         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8071         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8072         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8073         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8074         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8075         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8076         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8077         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8078         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8079         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8080         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8081         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8082         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8083         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8084         rsurface.modelelement3i = model->surfmesh.data_element3i;
8085         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8086         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8087         rsurface.modelelement3s = model->surfmesh.data_element3s;
8088         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8089         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8090         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8091         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8092         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8093         rsurface.modelsurfaces = model->data_surfaces;
8094         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8095         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8096         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8097         rsurface.modelgeneratedvertex = false;
8098         rsurface.batchgeneratedvertex = false;
8099         rsurface.batchfirstvertex = 0;
8100         rsurface.batchnumvertices = 0;
8101         rsurface.batchfirsttriangle = 0;
8102         rsurface.batchnumtriangles = 0;
8103         rsurface.batchvertex3f  = NULL;
8104         rsurface.batchvertex3f_vertexbuffer = NULL;
8105         rsurface.batchvertex3f_bufferoffset = 0;
8106         rsurface.batchsvector3f = NULL;
8107         rsurface.batchsvector3f_vertexbuffer = NULL;
8108         rsurface.batchsvector3f_bufferoffset = 0;
8109         rsurface.batchtvector3f = NULL;
8110         rsurface.batchtvector3f_vertexbuffer = NULL;
8111         rsurface.batchtvector3f_bufferoffset = 0;
8112         rsurface.batchnormal3f  = NULL;
8113         rsurface.batchnormal3f_vertexbuffer = NULL;
8114         rsurface.batchnormal3f_bufferoffset = 0;
8115         rsurface.batchlightmapcolor4f = NULL;
8116         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8117         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8118         rsurface.batchtexcoordtexture2f = NULL;
8119         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8120         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8121         rsurface.batchtexcoordlightmap2f = NULL;
8122         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8123         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8124         rsurface.batchvertexmesh = NULL;
8125         rsurface.batchvertexmeshbuffer = NULL;
8126         rsurface.batchvertex3fbuffer = NULL;
8127         rsurface.batchelement3i = NULL;
8128         rsurface.batchelement3i_indexbuffer = NULL;
8129         rsurface.batchelement3i_bufferoffset = 0;
8130         rsurface.batchelement3s = NULL;
8131         rsurface.batchelement3s_indexbuffer = NULL;
8132         rsurface.batchelement3s_bufferoffset = 0;
8133         rsurface.passcolor4f = NULL;
8134         rsurface.passcolor4f_vertexbuffer = NULL;
8135         rsurface.passcolor4f_bufferoffset = 0;
8136 }
8137
8138 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8139 {
8140         dp_model_t *model = ent->model;
8141         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8142         //      return;
8143         rsurface.entity = (entity_render_t *)ent;
8144         rsurface.skeleton = ent->skeleton;
8145         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8146         rsurface.ent_skinnum = ent->skinnum;
8147         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;
8148         rsurface.ent_flags = ent->flags;
8149         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8150         rsurface.matrix = ent->matrix;
8151         rsurface.inversematrix = ent->inversematrix;
8152         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8153         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8154         R_EntityMatrix(&rsurface.matrix);
8155         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8156         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8157         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8158         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8159         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8160         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8161         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8162         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8163         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8164         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8165         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8166         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8167         rsurface.colormod[3] = ent->alpha;
8168         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8169         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8170         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8171         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8172         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8173         if (ent->model->brush.submodel && !prepass)
8174         {
8175                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8176                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8177         }
8178         if (model->surfmesh.isanimated && model->AnimateVertices)
8179         {
8180                 if (ent->animcache_vertex3f)
8181                 {
8182                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8183                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8184                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8185                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8186                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8187                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8188                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8189                 }
8190                 else if (wanttangents)
8191                 {
8192                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8193                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8194                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8195                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8196                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8197                         rsurface.modelvertexmesh = NULL;
8198                         rsurface.modelvertexmeshbuffer = NULL;
8199                         rsurface.modelvertex3fbuffer = NULL;
8200                 }
8201                 else if (wantnormals)
8202                 {
8203                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8204                         rsurface.modelsvector3f = NULL;
8205                         rsurface.modeltvector3f = NULL;
8206                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8207                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8208                         rsurface.modelvertexmesh = NULL;
8209                         rsurface.modelvertexmeshbuffer = NULL;
8210                         rsurface.modelvertex3fbuffer = NULL;
8211                 }
8212                 else
8213                 {
8214                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8215                         rsurface.modelsvector3f = NULL;
8216                         rsurface.modeltvector3f = NULL;
8217                         rsurface.modelnormal3f = NULL;
8218                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8219                         rsurface.modelvertexmesh = NULL;
8220                         rsurface.modelvertexmeshbuffer = NULL;
8221                         rsurface.modelvertex3fbuffer = NULL;
8222                 }
8223                 rsurface.modelvertex3f_vertexbuffer = 0;
8224                 rsurface.modelvertex3f_bufferoffset = 0;
8225                 rsurface.modelsvector3f_vertexbuffer = 0;
8226                 rsurface.modelsvector3f_bufferoffset = 0;
8227                 rsurface.modeltvector3f_vertexbuffer = 0;
8228                 rsurface.modeltvector3f_bufferoffset = 0;
8229                 rsurface.modelnormal3f_vertexbuffer = 0;
8230                 rsurface.modelnormal3f_bufferoffset = 0;
8231                 rsurface.modelgeneratedvertex = true;
8232         }
8233         else
8234         {
8235                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8236                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8237                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8238                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8239                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8240                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8241                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8242                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8243                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8244                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8245                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8246                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8247                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8248                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8249                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8250                 rsurface.modelgeneratedvertex = false;
8251         }
8252         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8253         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8254         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8255         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8256         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8257         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8258         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8259         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8260         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8261         rsurface.modelelement3i = model->surfmesh.data_element3i;
8262         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8263         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8264         rsurface.modelelement3s = model->surfmesh.data_element3s;
8265         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8266         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8267         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8268         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8269         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8270         rsurface.modelsurfaces = model->data_surfaces;
8271         rsurface.batchgeneratedvertex = false;
8272         rsurface.batchfirstvertex = 0;
8273         rsurface.batchnumvertices = 0;
8274         rsurface.batchfirsttriangle = 0;
8275         rsurface.batchnumtriangles = 0;
8276         rsurface.batchvertex3f  = NULL;
8277         rsurface.batchvertex3f_vertexbuffer = NULL;
8278         rsurface.batchvertex3f_bufferoffset = 0;
8279         rsurface.batchsvector3f = NULL;
8280         rsurface.batchsvector3f_vertexbuffer = NULL;
8281         rsurface.batchsvector3f_bufferoffset = 0;
8282         rsurface.batchtvector3f = NULL;
8283         rsurface.batchtvector3f_vertexbuffer = NULL;
8284         rsurface.batchtvector3f_bufferoffset = 0;
8285         rsurface.batchnormal3f  = NULL;
8286         rsurface.batchnormal3f_vertexbuffer = NULL;
8287         rsurface.batchnormal3f_bufferoffset = 0;
8288         rsurface.batchlightmapcolor4f = NULL;
8289         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8290         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8291         rsurface.batchtexcoordtexture2f = NULL;
8292         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8293         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8294         rsurface.batchtexcoordlightmap2f = NULL;
8295         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8296         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8297         rsurface.batchvertexmesh = NULL;
8298         rsurface.batchvertexmeshbuffer = NULL;
8299         rsurface.batchvertex3fbuffer = NULL;
8300         rsurface.batchelement3i = NULL;
8301         rsurface.batchelement3i_indexbuffer = NULL;
8302         rsurface.batchelement3i_bufferoffset = 0;
8303         rsurface.batchelement3s = NULL;
8304         rsurface.batchelement3s_indexbuffer = NULL;
8305         rsurface.batchelement3s_bufferoffset = 0;
8306         rsurface.passcolor4f = NULL;
8307         rsurface.passcolor4f_vertexbuffer = NULL;
8308         rsurface.passcolor4f_bufferoffset = 0;
8309 }
8310
8311 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)
8312 {
8313         rsurface.entity = r_refdef.scene.worldentity;
8314         rsurface.skeleton = NULL;
8315         rsurface.ent_skinnum = 0;
8316         rsurface.ent_qwskin = -1;
8317         rsurface.ent_flags = entflags;
8318         rsurface.shadertime = r_refdef.scene.time - shadertime;
8319         rsurface.modelnumvertices = numvertices;
8320         rsurface.modelnumtriangles = numtriangles;
8321         rsurface.matrix = *matrix;
8322         rsurface.inversematrix = *inversematrix;
8323         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8324         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8325         R_EntityMatrix(&rsurface.matrix);
8326         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8327         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8328         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8329         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8330         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8331         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8332         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8333         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8334         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8335         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8336         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8337         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8338         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);
8339         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8340         rsurface.frameblend[0].lerp = 1;
8341         rsurface.ent_alttextures = false;
8342         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8343         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8344         if (wanttangents)
8345         {
8346                 rsurface.modelvertex3f = (float *)vertex3f;
8347                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8348                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8349                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8350         }
8351         else if (wantnormals)
8352         {
8353                 rsurface.modelvertex3f = (float *)vertex3f;
8354                 rsurface.modelsvector3f = NULL;
8355                 rsurface.modeltvector3f = NULL;
8356                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8357         }
8358         else
8359         {
8360                 rsurface.modelvertex3f = (float *)vertex3f;
8361                 rsurface.modelsvector3f = NULL;
8362                 rsurface.modeltvector3f = NULL;
8363                 rsurface.modelnormal3f = NULL;
8364         }
8365         rsurface.modelvertexmesh = NULL;
8366         rsurface.modelvertexmeshbuffer = NULL;
8367         rsurface.modelvertex3fbuffer = NULL;
8368         rsurface.modelvertex3f_vertexbuffer = 0;
8369         rsurface.modelvertex3f_bufferoffset = 0;
8370         rsurface.modelsvector3f_vertexbuffer = 0;
8371         rsurface.modelsvector3f_bufferoffset = 0;
8372         rsurface.modeltvector3f_vertexbuffer = 0;
8373         rsurface.modeltvector3f_bufferoffset = 0;
8374         rsurface.modelnormal3f_vertexbuffer = 0;
8375         rsurface.modelnormal3f_bufferoffset = 0;
8376         rsurface.modelgeneratedvertex = true;
8377         rsurface.modellightmapcolor4f  = (float *)color4f;
8378         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8379         rsurface.modellightmapcolor4f_bufferoffset = 0;
8380         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8381         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8382         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8383         rsurface.modeltexcoordlightmap2f  = NULL;
8384         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8385         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8386         rsurface.modelelement3i = (int *)element3i;
8387         rsurface.modelelement3i_indexbuffer = NULL;
8388         rsurface.modelelement3i_bufferoffset = 0;
8389         rsurface.modelelement3s = (unsigned short *)element3s;
8390         rsurface.modelelement3s_indexbuffer = NULL;
8391         rsurface.modelelement3s_bufferoffset = 0;
8392         rsurface.modellightmapoffsets = NULL;
8393         rsurface.modelsurfaces = NULL;
8394         rsurface.batchgeneratedvertex = false;
8395         rsurface.batchfirstvertex = 0;
8396         rsurface.batchnumvertices = 0;
8397         rsurface.batchfirsttriangle = 0;
8398         rsurface.batchnumtriangles = 0;
8399         rsurface.batchvertex3f  = NULL;
8400         rsurface.batchvertex3f_vertexbuffer = NULL;
8401         rsurface.batchvertex3f_bufferoffset = 0;
8402         rsurface.batchsvector3f = NULL;
8403         rsurface.batchsvector3f_vertexbuffer = NULL;
8404         rsurface.batchsvector3f_bufferoffset = 0;
8405         rsurface.batchtvector3f = NULL;
8406         rsurface.batchtvector3f_vertexbuffer = NULL;
8407         rsurface.batchtvector3f_bufferoffset = 0;
8408         rsurface.batchnormal3f  = NULL;
8409         rsurface.batchnormal3f_vertexbuffer = NULL;
8410         rsurface.batchnormal3f_bufferoffset = 0;
8411         rsurface.batchlightmapcolor4f = NULL;
8412         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8413         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8414         rsurface.batchtexcoordtexture2f = NULL;
8415         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8416         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8417         rsurface.batchtexcoordlightmap2f = NULL;
8418         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8419         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8420         rsurface.batchvertexmesh = NULL;
8421         rsurface.batchvertexmeshbuffer = NULL;
8422         rsurface.batchvertex3fbuffer = NULL;
8423         rsurface.batchelement3i = NULL;
8424         rsurface.batchelement3i_indexbuffer = NULL;
8425         rsurface.batchelement3i_bufferoffset = 0;
8426         rsurface.batchelement3s = NULL;
8427         rsurface.batchelement3s_indexbuffer = NULL;
8428         rsurface.batchelement3s_bufferoffset = 0;
8429         rsurface.passcolor4f = NULL;
8430         rsurface.passcolor4f_vertexbuffer = NULL;
8431         rsurface.passcolor4f_bufferoffset = 0;
8432
8433         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8434         {
8435                 if ((wantnormals || wanttangents) && !normal3f)
8436                 {
8437                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8438                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8439                 }
8440                 if (wanttangents && !svector3f)
8441                 {
8442                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8443                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8444                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8445                 }
8446         }
8447 }
8448
8449 float RSurf_FogPoint(const float *v)
8450 {
8451         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8452         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8453         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8454         float FogHeightFade = r_refdef.fogheightfade;
8455         float fogfrac;
8456         unsigned int fogmasktableindex;
8457         if (r_refdef.fogplaneviewabove)
8458                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8459         else
8460                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8461         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8462         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8463 }
8464
8465 float RSurf_FogVertex(const float *v)
8466 {
8467         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8468         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8469         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8470         float FogHeightFade = rsurface.fogheightfade;
8471         float fogfrac;
8472         unsigned int fogmasktableindex;
8473         if (r_refdef.fogplaneviewabove)
8474                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8475         else
8476                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8477         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8478         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8479 }
8480
8481 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8482 {
8483         int i;
8484         for (i = 0;i < numelements;i++)
8485                 outelement3i[i] = inelement3i[i] + adjust;
8486 }
8487
8488 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8489 extern cvar_t gl_vbo;
8490 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8491 {
8492         int deformindex;
8493         int firsttriangle;
8494         int numtriangles;
8495         int firstvertex;
8496         int endvertex;
8497         int numvertices;
8498         int surfacefirsttriangle;
8499         int surfacenumtriangles;
8500         int surfacefirstvertex;
8501         int surfaceendvertex;
8502         int surfacenumvertices;
8503         int batchnumvertices;
8504         int batchnumtriangles;
8505         int needsupdate;
8506         int i, j;
8507         qboolean gaps;
8508         qboolean dynamicvertex;
8509         float amplitude;
8510         float animpos;
8511         float scale;
8512         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8513         float waveparms[4];
8514         q3shaderinfo_deform_t *deform;
8515         const msurface_t *surface, *firstsurface;
8516         r_vertexmesh_t *vertexmesh;
8517         if (!texturenumsurfaces)
8518                 return;
8519         // find vertex range of this surface batch
8520         gaps = false;
8521         firstsurface = texturesurfacelist[0];
8522         firsttriangle = firstsurface->num_firsttriangle;
8523         batchnumvertices = 0;
8524         batchnumtriangles = 0;
8525         firstvertex = endvertex = firstsurface->num_firstvertex;
8526         for (i = 0;i < texturenumsurfaces;i++)
8527         {
8528                 surface = texturesurfacelist[i];
8529                 if (surface != firstsurface + i)
8530                         gaps = true;
8531                 surfacefirstvertex = surface->num_firstvertex;
8532                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8533                 surfacenumvertices = surface->num_vertices;
8534                 surfacenumtriangles = surface->num_triangles;
8535                 if (firstvertex > surfacefirstvertex)
8536                         firstvertex = surfacefirstvertex;
8537                 if (endvertex < surfaceendvertex)
8538                         endvertex = surfaceendvertex;
8539                 batchnumvertices += surfacenumvertices;
8540                 batchnumtriangles += surfacenumtriangles;
8541         }
8542
8543         // we now know the vertex range used, and if there are any gaps in it
8544         rsurface.batchfirstvertex = firstvertex;
8545         rsurface.batchnumvertices = endvertex - firstvertex;
8546         rsurface.batchfirsttriangle = firsttriangle;
8547         rsurface.batchnumtriangles = batchnumtriangles;
8548
8549         // this variable holds flags for which properties have been updated that
8550         // may require regenerating vertexmesh array...
8551         needsupdate = 0;
8552
8553         // check if any dynamic vertex processing must occur
8554         dynamicvertex = false;
8555
8556         // if there is a chance of animated vertex colors, it's a dynamic batch
8557         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8558         {
8559                 dynamicvertex = true;
8560                 batchneed |= BATCHNEED_NOGAPS;
8561                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8562         }
8563
8564         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8565         {
8566                 switch (deform->deform)
8567                 {
8568                 default:
8569                 case Q3DEFORM_PROJECTIONSHADOW:
8570                 case Q3DEFORM_TEXT0:
8571                 case Q3DEFORM_TEXT1:
8572                 case Q3DEFORM_TEXT2:
8573                 case Q3DEFORM_TEXT3:
8574                 case Q3DEFORM_TEXT4:
8575                 case Q3DEFORM_TEXT5:
8576                 case Q3DEFORM_TEXT6:
8577                 case Q3DEFORM_TEXT7:
8578                 case Q3DEFORM_NONE:
8579                         break;
8580                 case Q3DEFORM_AUTOSPRITE:
8581                         dynamicvertex = true;
8582                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8583                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8584                         break;
8585                 case Q3DEFORM_AUTOSPRITE2:
8586                         dynamicvertex = true;
8587                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8588                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8589                         break;
8590                 case Q3DEFORM_NORMAL:
8591                         dynamicvertex = true;
8592                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8593                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8594                         break;
8595                 case Q3DEFORM_WAVE:
8596                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8597                                 break; // if wavefunc is a nop, ignore this transform
8598                         dynamicvertex = true;
8599                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8600                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8601                         break;
8602                 case Q3DEFORM_BULGE:
8603                         dynamicvertex = true;
8604                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8605                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8606                         break;
8607                 case Q3DEFORM_MOVE:
8608                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8609                                 break; // if wavefunc is a nop, ignore this transform
8610                         dynamicvertex = true;
8611                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8612                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8613                         break;
8614                 }
8615         }
8616         switch(rsurface.texture->tcgen.tcgen)
8617         {
8618         default:
8619         case Q3TCGEN_TEXTURE:
8620                 break;
8621         case Q3TCGEN_LIGHTMAP:
8622                 dynamicvertex = true;
8623                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8624                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8625                 break;
8626         case Q3TCGEN_VECTOR:
8627                 dynamicvertex = true;
8628                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8629                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8630                 break;
8631         case Q3TCGEN_ENVIRONMENT:
8632                 dynamicvertex = true;
8633                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8634                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8635                 break;
8636         }
8637         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8638         {
8639                 dynamicvertex = true;
8640                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8641                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8642         }
8643
8644         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8645         {
8646                 dynamicvertex = true;
8647                 batchneed |= BATCHNEED_NOGAPS;
8648                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8649         }
8650
8651         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8652         {
8653                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8654                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8655                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8656                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8657                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8658                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8659                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8660         }
8661
8662         // when the model data has no vertex buffer (dynamic mesh), we need to
8663         // eliminate gaps
8664         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8665                 batchneed |= BATCHNEED_NOGAPS;
8666
8667         // if needsupdate, we have to do a dynamic vertex batch for sure
8668         if (needsupdate & batchneed)
8669                 dynamicvertex = true;
8670
8671         // see if we need to build vertexmesh from arrays
8672         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8673                 dynamicvertex = true;
8674
8675         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8676         // also some drivers strongly dislike firstvertex
8677         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8678                 dynamicvertex = true;
8679
8680         rsurface.batchvertex3f = rsurface.modelvertex3f;
8681         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8682         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8683         rsurface.batchsvector3f = rsurface.modelsvector3f;
8684         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8685         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8686         rsurface.batchtvector3f = rsurface.modeltvector3f;
8687         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8688         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8689         rsurface.batchnormal3f = rsurface.modelnormal3f;
8690         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8691         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8692         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8693         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8694         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8695         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8696         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8697         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8698         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8699         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8700         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8701         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8702         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8703         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8704         rsurface.batchelement3i = rsurface.modelelement3i;
8705         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8706         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8707         rsurface.batchelement3s = rsurface.modelelement3s;
8708         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8709         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8710
8711         // if any dynamic vertex processing has to occur in software, we copy the
8712         // entire surface list together before processing to rebase the vertices
8713         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8714         //
8715         // if any gaps exist and we do not have a static vertex buffer, we have to
8716         // copy the surface list together to avoid wasting upload bandwidth on the
8717         // vertices in the gaps.
8718         //
8719         // if gaps exist and we have a static vertex buffer, we still have to
8720         // combine the index buffer ranges into one dynamic index buffer.
8721         //
8722         // in all cases we end up with data that can be drawn in one call.
8723
8724         if (!dynamicvertex)
8725         {
8726                 // static vertex data, just set pointers...
8727                 rsurface.batchgeneratedvertex = false;
8728                 // if there are gaps, we want to build a combined index buffer,
8729                 // otherwise use the original static buffer with an appropriate offset
8730                 if (gaps)
8731                 {
8732                         // build a new triangle elements array for this batch
8733                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8734                         rsurface.batchfirsttriangle = 0;
8735                         numtriangles = 0;
8736                         for (i = 0;i < texturenumsurfaces;i++)
8737                         {
8738                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8739                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8740                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8741                                 numtriangles += surfacenumtriangles;
8742                         }
8743                         rsurface.batchelement3i_indexbuffer = NULL;
8744                         rsurface.batchelement3i_bufferoffset = 0;
8745                         rsurface.batchelement3s = NULL;
8746                         rsurface.batchelement3s_indexbuffer = NULL;
8747                         rsurface.batchelement3s_bufferoffset = 0;
8748                         if (endvertex <= 65536)
8749                         {
8750                                 // make a 16bit (unsigned short) index array if possible
8751                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8752                                 for (i = 0;i < numtriangles*3;i++)
8753                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8754                         }
8755                 }
8756                 return;
8757         }
8758
8759         // something needs software processing, do it for real...
8760         // we only directly handle separate array data in this case and then
8761         // generate interleaved data if needed...
8762         rsurface.batchgeneratedvertex = true;
8763
8764         // now copy the vertex data into a combined array and make an index array
8765         // (this is what Quake3 does all the time)
8766         //if (gaps || rsurface.batchfirstvertex)
8767         {
8768                 rsurface.batchvertex3fbuffer = NULL;
8769                 rsurface.batchvertexmesh = NULL;
8770                 rsurface.batchvertexmeshbuffer = NULL;
8771                 rsurface.batchvertex3f = NULL;
8772                 rsurface.batchvertex3f_vertexbuffer = NULL;
8773                 rsurface.batchvertex3f_bufferoffset = 0;
8774                 rsurface.batchsvector3f = NULL;
8775                 rsurface.batchsvector3f_vertexbuffer = NULL;
8776                 rsurface.batchsvector3f_bufferoffset = 0;
8777                 rsurface.batchtvector3f = NULL;
8778                 rsurface.batchtvector3f_vertexbuffer = NULL;
8779                 rsurface.batchtvector3f_bufferoffset = 0;
8780                 rsurface.batchnormal3f = NULL;
8781                 rsurface.batchnormal3f_vertexbuffer = NULL;
8782                 rsurface.batchnormal3f_bufferoffset = 0;
8783                 rsurface.batchlightmapcolor4f = NULL;
8784                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8785                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8786                 rsurface.batchtexcoordtexture2f = NULL;
8787                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8788                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8789                 rsurface.batchtexcoordlightmap2f = NULL;
8790                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8791                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8792                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8793                 rsurface.batchelement3i_indexbuffer = NULL;
8794                 rsurface.batchelement3i_bufferoffset = 0;
8795                 rsurface.batchelement3s = NULL;
8796                 rsurface.batchelement3s_indexbuffer = NULL;
8797                 rsurface.batchelement3s_bufferoffset = 0;
8798                 // we'll only be setting up certain arrays as needed
8799                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8800                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8801                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8802                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8803                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8804                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8805                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8806                 {
8807                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8808                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8809                 }
8810                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8811                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8812                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8813                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8814                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8815                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8816                 numvertices = 0;
8817                 numtriangles = 0;
8818                 for (i = 0;i < texturenumsurfaces;i++)
8819                 {
8820                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8821                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8822                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8823                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8824                         // copy only the data requested
8825                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8826                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8827                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8828                         {
8829                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8830                                 {
8831                                         if (rsurface.batchvertex3f)
8832                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8833                                         else
8834                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8835                                 }
8836                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8837                                 {
8838                                         if (rsurface.modelnormal3f)
8839                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8840                                         else
8841                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8842                                 }
8843                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8844                                 {
8845                                         if (rsurface.modelsvector3f)
8846                                         {
8847                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8848                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8849                                         }
8850                                         else
8851                                         {
8852                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8853                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8854                                         }
8855                                 }
8856                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8857                                 {
8858                                         if (rsurface.modellightmapcolor4f)
8859                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8860                                         else
8861                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8862                                 }
8863                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8864                                 {
8865                                         if (rsurface.modeltexcoordtexture2f)
8866                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8867                                         else
8868                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8869                                 }
8870                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8871                                 {
8872                                         if (rsurface.modeltexcoordlightmap2f)
8873                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8874                                         else
8875                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8876                                 }
8877                         }
8878                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8879                         numvertices += surfacenumvertices;
8880                         numtriangles += surfacenumtriangles;
8881                 }
8882
8883                 // generate a 16bit index array as well if possible
8884                 // (in general, dynamic batches fit)
8885                 if (numvertices <= 65536)
8886                 {
8887                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8888                         for (i = 0;i < numtriangles*3;i++)
8889                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8890                 }
8891
8892                 // since we've copied everything, the batch now starts at 0
8893                 rsurface.batchfirstvertex = 0;
8894                 rsurface.batchnumvertices = batchnumvertices;
8895                 rsurface.batchfirsttriangle = 0;
8896                 rsurface.batchnumtriangles = batchnumtriangles;
8897         }
8898
8899         // q1bsp surfaces rendered in vertex color mode have to have colors
8900         // calculated based on lightstyles
8901         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8902         {
8903                 // generate color arrays for the surfaces in this list
8904                 int c[4];
8905                 int scale;
8906                 int size3;
8907                 const int *offsets;
8908                 const unsigned char *lm;
8909                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8910                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8911                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8912                 numvertices = 0;
8913                 for (i = 0;i < texturenumsurfaces;i++)
8914                 {
8915                         surface = texturesurfacelist[i];
8916                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8917                         surfacenumvertices = surface->num_vertices;
8918                         if (surface->lightmapinfo->samples)
8919                         {
8920                                 for (j = 0;j < surfacenumvertices;j++)
8921                                 {
8922                                         lm = surface->lightmapinfo->samples + offsets[j];
8923                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8924                                         VectorScale(lm, scale, c);
8925                                         if (surface->lightmapinfo->styles[1] != 255)
8926                                         {
8927                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8928                                                 lm += size3;
8929                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8930                                                 VectorMA(c, scale, lm, c);
8931                                                 if (surface->lightmapinfo->styles[2] != 255)
8932                                                 {
8933                                                         lm += size3;
8934                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8935                                                         VectorMA(c, scale, lm, c);
8936                                                         if (surface->lightmapinfo->styles[3] != 255)
8937                                                         {
8938                                                                 lm += size3;
8939                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8940                                                                 VectorMA(c, scale, lm, c);
8941                                                         }
8942                                                 }
8943                                         }
8944                                         c[0] >>= 7;
8945                                         c[1] >>= 7;
8946                                         c[2] >>= 7;
8947                                         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);
8948                                         numvertices++;
8949                                 }
8950                         }
8951                         else
8952                         {
8953                                 for (j = 0;j < surfacenumvertices;j++)
8954                                 {
8955                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8956                                         numvertices++;
8957                                 }
8958                         }
8959                 }
8960         }
8961
8962         // if vertices are deformed (sprite flares and things in maps, possibly
8963         // water waves, bulges and other deformations), modify the copied vertices
8964         // in place
8965         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8966         {
8967                 switch (deform->deform)
8968                 {
8969                 default:
8970                 case Q3DEFORM_PROJECTIONSHADOW:
8971                 case Q3DEFORM_TEXT0:
8972                 case Q3DEFORM_TEXT1:
8973                 case Q3DEFORM_TEXT2:
8974                 case Q3DEFORM_TEXT3:
8975                 case Q3DEFORM_TEXT4:
8976                 case Q3DEFORM_TEXT5:
8977                 case Q3DEFORM_TEXT6:
8978                 case Q3DEFORM_TEXT7:
8979                 case Q3DEFORM_NONE:
8980                         break;
8981                 case Q3DEFORM_AUTOSPRITE:
8982                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8983                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8984                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8985                         VectorNormalize(newforward);
8986                         VectorNormalize(newright);
8987                         VectorNormalize(newup);
8988 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8989 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
8990 //                      rsurface.batchvertex3f_bufferoffset = 0;
8991 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
8992 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
8993 //                      rsurface.batchsvector3f_bufferoffset = 0;
8994 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
8995 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
8996 //                      rsurface.batchtvector3f_bufferoffset = 0;
8997 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
8998 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
8999 //                      rsurface.batchnormal3f_bufferoffset = 0;
9000                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9001                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9002                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9003                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9004                                 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);
9005                         // a single autosprite surface can contain multiple sprites...
9006                         for (j = 0;j < batchnumvertices - 3;j += 4)
9007                         {
9008                                 VectorClear(center);
9009                                 for (i = 0;i < 4;i++)
9010                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9011                                 VectorScale(center, 0.25f, center);
9012                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9013                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9014                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9015                                 for (i = 0;i < 4;i++)
9016                                 {
9017                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9018                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9019                                 }
9020                         }
9021                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9022                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9023                         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);
9024                         break;
9025                 case Q3DEFORM_AUTOSPRITE2:
9026                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9027                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9028                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9029                         VectorNormalize(newforward);
9030                         VectorNormalize(newright);
9031                         VectorNormalize(newup);
9032 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9033 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9034 //                      rsurface.batchvertex3f_bufferoffset = 0;
9035                         {
9036                                 const float *v1, *v2;
9037                                 vec3_t start, end;
9038                                 float f, l;
9039                                 struct
9040                                 {
9041                                         float length2;
9042                                         const float *v1;
9043                                         const float *v2;
9044                                 }
9045                                 shortest[2];
9046                                 memset(shortest, 0, sizeof(shortest));
9047                                 // a single autosprite surface can contain multiple sprites...
9048                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9049                                 {
9050                                         VectorClear(center);
9051                                         for (i = 0;i < 4;i++)
9052                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9053                                         VectorScale(center, 0.25f, center);
9054                                         // find the two shortest edges, then use them to define the
9055                                         // axis vectors for rotating around the central axis
9056                                         for (i = 0;i < 6;i++)
9057                                         {
9058                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9059                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9060                                                 l = VectorDistance2(v1, v2);
9061                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9062                                                 if (v1[2] != v2[2])
9063                                                         l += (1.0f / 1024.0f);
9064                                                 if (shortest[0].length2 > l || i == 0)
9065                                                 {
9066                                                         shortest[1] = shortest[0];
9067                                                         shortest[0].length2 = l;
9068                                                         shortest[0].v1 = v1;
9069                                                         shortest[0].v2 = v2;
9070                                                 }
9071                                                 else if (shortest[1].length2 > l || i == 1)
9072                                                 {
9073                                                         shortest[1].length2 = l;
9074                                                         shortest[1].v1 = v1;
9075                                                         shortest[1].v2 = v2;
9076                                                 }
9077                                         }
9078                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9079                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9080                                         // this calculates the right vector from the shortest edge
9081                                         // and the up vector from the edge midpoints
9082                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9083                                         VectorNormalize(right);
9084                                         VectorSubtract(end, start, up);
9085                                         VectorNormalize(up);
9086                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9087                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9088                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9089                                         VectorNegate(forward, forward);
9090                                         VectorReflect(forward, 0, up, forward);
9091                                         VectorNormalize(forward);
9092                                         CrossProduct(up, forward, newright);
9093                                         VectorNormalize(newright);
9094                                         // rotate the quad around the up axis vector, this is made
9095                                         // especially easy by the fact we know the quad is flat,
9096                                         // so we only have to subtract the center position and
9097                                         // measure distance along the right vector, and then
9098                                         // multiply that by the newright vector and add back the
9099                                         // center position
9100                                         // we also need to subtract the old position to undo the
9101                                         // displacement from the center, which we do with a
9102                                         // DotProduct, the subtraction/addition of center is also
9103                                         // optimized into DotProducts here
9104                                         l = DotProduct(right, center);
9105                                         for (i = 0;i < 4;i++)
9106                                         {
9107                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9108                                                 f = DotProduct(right, v1) - l;
9109                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9110                                         }
9111                                 }
9112                         }
9113                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9114                         {
9115 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9116 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9117 //                              rsurface.batchnormal3f_bufferoffset = 0;
9118                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9119                         }
9120                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9121                         {
9122 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9123 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9124 //                              rsurface.batchsvector3f_bufferoffset = 0;
9125 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9126 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9127 //                              rsurface.batchtvector3f_bufferoffset = 0;
9128                                 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);
9129                         }
9130                         break;
9131                 case Q3DEFORM_NORMAL:
9132                         // deform the normals to make reflections wavey
9133                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9134                         rsurface.batchnormal3f_vertexbuffer = NULL;
9135                         rsurface.batchnormal3f_bufferoffset = 0;
9136                         for (j = 0;j < batchnumvertices;j++)
9137                         {
9138                                 float vertex[3];
9139                                 float *normal = rsurface.batchnormal3f + 3*j;
9140                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9141                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9142                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9143                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9144                                 VectorNormalize(normal);
9145                         }
9146                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9147                         {
9148 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9149 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9150 //                              rsurface.batchsvector3f_bufferoffset = 0;
9151 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9152 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9153 //                              rsurface.batchtvector3f_bufferoffset = 0;
9154                                 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);
9155                         }
9156                         break;
9157                 case Q3DEFORM_WAVE:
9158                         // deform vertex array to make wavey water and flags and such
9159                         waveparms[0] = deform->waveparms[0];
9160                         waveparms[1] = deform->waveparms[1];
9161                         waveparms[2] = deform->waveparms[2];
9162                         waveparms[3] = deform->waveparms[3];
9163                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9164                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9165                         // this is how a divisor of vertex influence on deformation
9166                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9167                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9168 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9169 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9170 //                      rsurface.batchvertex3f_bufferoffset = 0;
9171 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9172 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9173 //                      rsurface.batchnormal3f_bufferoffset = 0;
9174                         for (j = 0;j < batchnumvertices;j++)
9175                         {
9176                                 // if the wavefunc depends on time, evaluate it per-vertex
9177                                 if (waveparms[3])
9178                                 {
9179                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9180                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9181                                 }
9182                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9183                         }
9184                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9185                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9186                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9187                         {
9188 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9189 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9190 //                              rsurface.batchsvector3f_bufferoffset = 0;
9191 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9192 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9193 //                              rsurface.batchtvector3f_bufferoffset = 0;
9194                                 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);
9195                         }
9196                         break;
9197                 case Q3DEFORM_BULGE:
9198                         // deform vertex array to make the surface have moving bulges
9199 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9200 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9201 //                      rsurface.batchvertex3f_bufferoffset = 0;
9202 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9203 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9204 //                      rsurface.batchnormal3f_bufferoffset = 0;
9205                         for (j = 0;j < batchnumvertices;j++)
9206                         {
9207                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9208                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9209                         }
9210                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9211                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9212                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9213                         {
9214 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9215 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9216 //                              rsurface.batchsvector3f_bufferoffset = 0;
9217 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9218 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9219 //                              rsurface.batchtvector3f_bufferoffset = 0;
9220                                 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);
9221                         }
9222                         break;
9223                 case Q3DEFORM_MOVE:
9224                         // deform vertex array
9225                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9226                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9227                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9228                         VectorScale(deform->parms, scale, waveparms);
9229 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9230 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9231 //                      rsurface.batchvertex3f_bufferoffset = 0;
9232                         for (j = 0;j < batchnumvertices;j++)
9233                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9234                         break;
9235                 }
9236         }
9237
9238         // generate texcoords based on the chosen texcoord source
9239         switch(rsurface.texture->tcgen.tcgen)
9240         {
9241         default:
9242         case Q3TCGEN_TEXTURE:
9243                 break;
9244         case Q3TCGEN_LIGHTMAP:
9245 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9246 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9247 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9248                 if (rsurface.batchtexcoordlightmap2f)
9249                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9250                 break;
9251         case Q3TCGEN_VECTOR:
9252 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9253 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9254 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9255                 for (j = 0;j < batchnumvertices;j++)
9256                 {
9257                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9258                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9259                 }
9260                 break;
9261         case Q3TCGEN_ENVIRONMENT:
9262                 // make environment reflections using a spheremap
9263                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9264                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9265                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9266                 for (j = 0;j < batchnumvertices;j++)
9267                 {
9268                         // identical to Q3A's method, but executed in worldspace so
9269                         // carried models can be shiny too
9270
9271                         float viewer[3], d, reflected[3], worldreflected[3];
9272
9273                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9274                         // VectorNormalize(viewer);
9275
9276                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9277
9278                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9279                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9280                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9281                         // note: this is proportinal to viewer, so we can normalize later
9282
9283                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9284                         VectorNormalize(worldreflected);
9285
9286                         // note: this sphere map only uses world x and z!
9287                         // so positive and negative y will LOOK THE SAME.
9288                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9289                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9290                 }
9291                 break;
9292         }
9293         // the only tcmod that needs software vertex processing is turbulent, so
9294         // check for it here and apply the changes if needed
9295         // and we only support that as the first one
9296         // (handling a mixture of turbulent and other tcmods would be problematic
9297         //  without punting it entirely to a software path)
9298         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9299         {
9300                 amplitude = rsurface.texture->tcmods[0].parms[1];
9301                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9302 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9303 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9304 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9305                 for (j = 0;j < batchnumvertices;j++)
9306                 {
9307                         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);
9308                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9309                 }
9310         }
9311
9312         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9313         {
9314                 // convert the modified arrays to vertex structs
9315 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9316 //              rsurface.batchvertexmeshbuffer = NULL;
9317                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9318                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9319                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9320                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9321                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9322                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9323                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9324                 {
9325                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9326                         {
9327                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9328                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9329                         }
9330                 }
9331                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9332                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9333                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9334                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9335                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9336                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9337                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9338                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9339                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9340         }
9341 }
9342
9343 void RSurf_DrawBatch(void)
9344 {
9345         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9346         // through the pipeline, killing it earlier in the pipeline would have
9347         // per-surface overhead rather than per-batch overhead, so it's best to
9348         // reject it here, before it hits glDraw.
9349         if (rsurface.batchnumtriangles == 0)
9350                 return;
9351 #if 0
9352         // batch debugging code
9353         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9354         {
9355                 int i;
9356                 int j;
9357                 int c;
9358                 const int *e;
9359                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9360                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9361                 {
9362                         c = e[i];
9363                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9364                         {
9365                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9366                                 {
9367                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9368                                                 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);
9369                                         break;
9370                                 }
9371                         }
9372                 }
9373         }
9374 #endif
9375         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);
9376 }
9377
9378 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9379 {
9380         // pick the closest matching water plane
9381         int planeindex, vertexindex, bestplaneindex = -1;
9382         float d, bestd;
9383         vec3_t vert;
9384         const float *v;
9385         r_waterstate_waterplane_t *p;
9386         qboolean prepared = false;
9387         bestd = 0;
9388         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9389         {
9390                 if(p->camera_entity != rsurface.texture->camera_entity)
9391                         continue;
9392                 d = 0;
9393                 if(!prepared)
9394                 {
9395                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9396                         prepared = true;
9397                         if(rsurface.batchnumvertices == 0)
9398                                 break;
9399                 }
9400                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9401                 {
9402                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9403                         d += fabs(PlaneDiff(vert, &p->plane));
9404                 }
9405                 if (bestd > d || bestplaneindex < 0)
9406                 {
9407                         bestd = d;
9408                         bestplaneindex = planeindex;
9409                 }
9410         }
9411         return bestplaneindex;
9412         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9413         // this situation though, as it might be better to render single larger
9414         // batches with useless stuff (backface culled for example) than to
9415         // render multiple smaller batches
9416 }
9417
9418 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9419 {
9420         int i;
9421         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9422         rsurface.passcolor4f_vertexbuffer = 0;
9423         rsurface.passcolor4f_bufferoffset = 0;
9424         for (i = 0;i < rsurface.batchnumvertices;i++)
9425                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9426 }
9427
9428 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9429 {
9430         int i;
9431         float f;
9432         const float *v;
9433         const float *c;
9434         float *c2;
9435         if (rsurface.passcolor4f)
9436         {
9437                 // generate color arrays
9438                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9439                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9440                 rsurface.passcolor4f_vertexbuffer = 0;
9441                 rsurface.passcolor4f_bufferoffset = 0;
9442                 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)
9443                 {
9444                         f = RSurf_FogVertex(v);
9445                         c2[0] = c[0] * f;
9446                         c2[1] = c[1] * f;
9447                         c2[2] = c[2] * f;
9448                         c2[3] = c[3];
9449                 }
9450         }
9451         else
9452         {
9453                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9454                 rsurface.passcolor4f_vertexbuffer = 0;
9455                 rsurface.passcolor4f_bufferoffset = 0;
9456                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9457                 {
9458                         f = RSurf_FogVertex(v);
9459                         c2[0] = f;
9460                         c2[1] = f;
9461                         c2[2] = f;
9462                         c2[3] = 1;
9463                 }
9464         }
9465 }
9466
9467 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9468 {
9469         int i;
9470         float f;
9471         const float *v;
9472         const float *c;
9473         float *c2;
9474         if (!rsurface.passcolor4f)
9475                 return;
9476         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9477         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9478         rsurface.passcolor4f_vertexbuffer = 0;
9479         rsurface.passcolor4f_bufferoffset = 0;
9480         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)
9481         {
9482                 f = RSurf_FogVertex(v);
9483                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9484                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9485                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9486                 c2[3] = c[3];
9487         }
9488 }
9489
9490 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9491 {
9492         int i;
9493         const float *c;
9494         float *c2;
9495         if (!rsurface.passcolor4f)
9496                 return;
9497         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9498         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9499         rsurface.passcolor4f_vertexbuffer = 0;
9500         rsurface.passcolor4f_bufferoffset = 0;
9501         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9502         {
9503                 c2[0] = c[0] * r;
9504                 c2[1] = c[1] * g;
9505                 c2[2] = c[2] * b;
9506                 c2[3] = c[3] * a;
9507         }
9508 }
9509
9510 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9511 {
9512         int i;
9513         const float *c;
9514         float *c2;
9515         if (!rsurface.passcolor4f)
9516                 return;
9517         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9518         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9519         rsurface.passcolor4f_vertexbuffer = 0;
9520         rsurface.passcolor4f_bufferoffset = 0;
9521         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9522         {
9523                 c2[0] = c[0] + r_refdef.scene.ambient;
9524                 c2[1] = c[1] + r_refdef.scene.ambient;
9525                 c2[2] = c[2] + r_refdef.scene.ambient;
9526                 c2[3] = c[3];
9527         }
9528 }
9529
9530 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9531 {
9532         // TODO: optimize
9533         rsurface.passcolor4f = NULL;
9534         rsurface.passcolor4f_vertexbuffer = 0;
9535         rsurface.passcolor4f_bufferoffset = 0;
9536         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9537         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9538         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9539         GL_Color(r, g, b, a);
9540         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9541         RSurf_DrawBatch();
9542 }
9543
9544 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9545 {
9546         // TODO: optimize applyfog && applycolor case
9547         // just apply fog if necessary, and tint the fog color array if necessary
9548         rsurface.passcolor4f = NULL;
9549         rsurface.passcolor4f_vertexbuffer = 0;
9550         rsurface.passcolor4f_bufferoffset = 0;
9551         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9552         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9553         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9554         GL_Color(r, g, b, a);
9555         RSurf_DrawBatch();
9556 }
9557
9558 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9559 {
9560         // TODO: optimize
9561         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9562         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9563         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9564         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9565         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9566         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9567         GL_Color(r, g, b, a);
9568         RSurf_DrawBatch();
9569 }
9570
9571 static void RSurf_DrawBatch_GL11_ClampColor(void)
9572 {
9573         int i;
9574         const float *c1;
9575         float *c2;
9576         if (!rsurface.passcolor4f)
9577                 return;
9578         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9579         {
9580                 c2[0] = bound(0.0f, c1[0], 1.0f);
9581                 c2[1] = bound(0.0f, c1[1], 1.0f);
9582                 c2[2] = bound(0.0f, c1[2], 1.0f);
9583                 c2[3] = bound(0.0f, c1[3], 1.0f);
9584         }
9585 }
9586
9587 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9588 {
9589         int i;
9590         float f;
9591         const float *v;
9592         const float *n;
9593         float *c;
9594         //vec3_t eyedir;
9595
9596         // fake shading
9597         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9598         rsurface.passcolor4f_vertexbuffer = 0;
9599         rsurface.passcolor4f_bufferoffset = 0;
9600         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)
9601         {
9602                 f = -DotProduct(r_refdef.view.forward, n);
9603                 f = max(0, f);
9604                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9605                 f *= r_refdef.lightmapintensity;
9606                 Vector4Set(c, f, f, f, 1);
9607         }
9608 }
9609
9610 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9611 {
9612         RSurf_DrawBatch_GL11_ApplyFakeLight();
9613         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9614         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9615         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9616         GL_Color(r, g, b, a);
9617         RSurf_DrawBatch();
9618 }
9619
9620 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9621 {
9622         int i;
9623         float f;
9624         float alpha;
9625         const float *v;
9626         const float *n;
9627         float *c;
9628         vec3_t ambientcolor;
9629         vec3_t diffusecolor;
9630         vec3_t lightdir;
9631         // TODO: optimize
9632         // model lighting
9633         VectorCopy(rsurface.modellight_lightdir, lightdir);
9634         f = 0.5f * r_refdef.lightmapintensity;
9635         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9636         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9637         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9638         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9639         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9640         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9641         alpha = *a;
9642         if (VectorLength2(diffusecolor) > 0)
9643         {
9644                 // q3-style directional shading
9645                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9646                 rsurface.passcolor4f_vertexbuffer = 0;
9647                 rsurface.passcolor4f_bufferoffset = 0;
9648                 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)
9649                 {
9650                         if ((f = DotProduct(n, lightdir)) > 0)
9651                                 VectorMA(ambientcolor, f, diffusecolor, c);
9652                         else
9653                                 VectorCopy(ambientcolor, c);
9654                         c[3] = alpha;
9655                 }
9656                 *r = 1;
9657                 *g = 1;
9658                 *b = 1;
9659                 *a = 1;
9660                 *applycolor = false;
9661         }
9662         else
9663         {
9664                 *r = ambientcolor[0];
9665                 *g = ambientcolor[1];
9666                 *b = ambientcolor[2];
9667                 rsurface.passcolor4f = NULL;
9668                 rsurface.passcolor4f_vertexbuffer = 0;
9669                 rsurface.passcolor4f_bufferoffset = 0;
9670         }
9671 }
9672
9673 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9674 {
9675         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9676         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9677         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9678         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9679         GL_Color(r, g, b, a);
9680         RSurf_DrawBatch();
9681 }
9682
9683 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9684 {
9685         int i;
9686         float f;
9687         const float *v;
9688         float *c;
9689
9690         // fake shading
9691         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9692         rsurface.passcolor4f_vertexbuffer = 0;
9693         rsurface.passcolor4f_bufferoffset = 0;
9694
9695         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9696         {
9697                 f = 1 - RSurf_FogVertex(v);
9698                 c[0] = r;
9699                 c[1] = g;
9700                 c[2] = b;
9701                 c[3] = f * a;
9702         }
9703 }
9704
9705 void RSurf_SetupDepthAndCulling(void)
9706 {
9707         // submodels are biased to avoid z-fighting with world surfaces that they
9708         // may be exactly overlapping (avoids z-fighting artifacts on certain
9709         // doors and things in Quake maps)
9710         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9711         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9712         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9713         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9714 }
9715
9716 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9717 {
9718         // transparent sky would be ridiculous
9719         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9720                 return;
9721         R_SetupShader_Generic_NoTexture(false, false);
9722         skyrenderlater = true;
9723         RSurf_SetupDepthAndCulling();
9724         GL_DepthMask(true);
9725         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9726         // skymasking on them, and Quake3 never did sky masking (unlike
9727         // software Quake and software Quake2), so disable the sky masking
9728         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9729         // and skymasking also looks very bad when noclipping outside the
9730         // level, so don't use it then either.
9731         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9732         {
9733                 R_Mesh_ResetTextureState();
9734                 if (skyrendermasked)
9735                 {
9736                         R_SetupShader_DepthOrShadow(false, false);
9737                         // depth-only (masking)
9738                         GL_ColorMask(0,0,0,0);
9739                         // just to make sure that braindead drivers don't draw
9740                         // anything despite that colormask...
9741                         GL_BlendFunc(GL_ZERO, GL_ONE);
9742                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9743                         if (rsurface.batchvertex3fbuffer)
9744                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9745                         else
9746                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9747                 }
9748                 else
9749                 {
9750                         R_SetupShader_Generic_NoTexture(false, false);
9751                         // fog sky
9752                         GL_BlendFunc(GL_ONE, GL_ZERO);
9753                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9754                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9755                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9756                 }
9757                 RSurf_DrawBatch();
9758                 if (skyrendermasked)
9759                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9760         }
9761         R_Mesh_ResetTextureState();
9762         GL_Color(1, 1, 1, 1);
9763 }
9764
9765 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9766 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9767 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9768 {
9769         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9770                 return;
9771         if (prepass)
9772         {
9773                 // render screenspace normalmap to texture
9774                 GL_DepthMask(true);
9775                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9776                 RSurf_DrawBatch();
9777                 return;
9778         }
9779
9780         // bind lightmap texture
9781
9782         // water/refraction/reflection/camera surfaces have to be handled specially
9783         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9784         {
9785                 int start, end, startplaneindex;
9786                 for (start = 0;start < texturenumsurfaces;start = end)
9787                 {
9788                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9789                         if(startplaneindex < 0)
9790                         {
9791                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9792                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9793                                 end = start + 1;
9794                                 continue;
9795                         }
9796                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9797                                 ;
9798                         // now that we have a batch using the same planeindex, render it
9799                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9800                         {
9801                                 // render water or distortion background
9802                                 GL_DepthMask(true);
9803                                 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);
9804                                 RSurf_DrawBatch();
9805                                 // blend surface on top
9806                                 GL_DepthMask(false);
9807                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9808                                 RSurf_DrawBatch();
9809                         }
9810                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9811                         {
9812                                 // render surface with reflection texture as input
9813                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9814                                 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);
9815                                 RSurf_DrawBatch();
9816                         }
9817                 }
9818                 return;
9819         }
9820
9821         // render surface batch normally
9822         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9823         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);
9824         RSurf_DrawBatch();
9825 }
9826
9827 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9828 {
9829         // OpenGL 1.3 path - anything not completely ancient
9830         qboolean applycolor;
9831         qboolean applyfog;
9832         int layerindex;
9833         const texturelayer_t *layer;
9834         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);
9835         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9836
9837         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9838         {
9839                 vec4_t layercolor;
9840                 int layertexrgbscale;
9841                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9842                 {
9843                         if (layerindex == 0)
9844                                 GL_AlphaTest(true);
9845                         else
9846                         {
9847                                 GL_AlphaTest(false);
9848                                 GL_DepthFunc(GL_EQUAL);
9849                         }
9850                 }
9851                 GL_DepthMask(layer->depthmask && writedepth);
9852                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9853                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9854                 {
9855                         layertexrgbscale = 4;
9856                         VectorScale(layer->color, 0.25f, layercolor);
9857                 }
9858                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9859                 {
9860                         layertexrgbscale = 2;
9861                         VectorScale(layer->color, 0.5f, layercolor);
9862                 }
9863                 else
9864                 {
9865                         layertexrgbscale = 1;
9866                         VectorScale(layer->color, 1.0f, layercolor);
9867                 }
9868                 layercolor[3] = layer->color[3];
9869                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9870                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9871                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9872                 switch (layer->type)
9873                 {
9874                 case TEXTURELAYERTYPE_LITTEXTURE:
9875                         // single-pass lightmapped texture with 2x rgbscale
9876                         R_Mesh_TexBind(0, r_texture_white);
9877                         R_Mesh_TexMatrix(0, NULL);
9878                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9879                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9880                         R_Mesh_TexBind(1, layer->texture);
9881                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9882                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9883                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9884                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9885                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9886                         else if (FAKELIGHT_ENABLED)
9887                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9888                         else if (rsurface.uselightmaptexture)
9889                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9890                         else
9891                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9892                         break;
9893                 case TEXTURELAYERTYPE_TEXTURE:
9894                         // singletexture unlit texture with transparency support
9895                         R_Mesh_TexBind(0, layer->texture);
9896                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9897                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9898                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9899                         R_Mesh_TexBind(1, 0);
9900                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9901                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9902                         break;
9903                 case TEXTURELAYERTYPE_FOG:
9904                         // singletexture fogging
9905                         if (layer->texture)
9906                         {
9907                                 R_Mesh_TexBind(0, layer->texture);
9908                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9909                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9910                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9911                         }
9912                         else
9913                         {
9914                                 R_Mesh_TexBind(0, 0);
9915                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9916                         }
9917                         R_Mesh_TexBind(1, 0);
9918                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9919                         // generate a color array for the fog pass
9920                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9921                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9922                         RSurf_DrawBatch();
9923                         break;
9924                 default:
9925                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9926                 }
9927         }
9928         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9929         {
9930                 GL_DepthFunc(GL_LEQUAL);
9931                 GL_AlphaTest(false);
9932         }
9933 }
9934
9935 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9936 {
9937         // OpenGL 1.1 - crusty old voodoo path
9938         qboolean applyfog;
9939         int layerindex;
9940         const texturelayer_t *layer;
9941         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);
9942         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9943
9944         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9945         {
9946                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9947                 {
9948                         if (layerindex == 0)
9949                                 GL_AlphaTest(true);
9950                         else
9951                         {
9952                                 GL_AlphaTest(false);
9953                                 GL_DepthFunc(GL_EQUAL);
9954                         }
9955                 }
9956                 GL_DepthMask(layer->depthmask && writedepth);
9957                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9958                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9959                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9960                 switch (layer->type)
9961                 {
9962                 case TEXTURELAYERTYPE_LITTEXTURE:
9963                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9964                         {
9965                                 // two-pass lit texture with 2x rgbscale
9966                                 // first the lightmap pass
9967                                 R_Mesh_TexBind(0, r_texture_white);
9968                                 R_Mesh_TexMatrix(0, NULL);
9969                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9970                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9971                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9972                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9973                                 else if (FAKELIGHT_ENABLED)
9974                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9975                                 else if (rsurface.uselightmaptexture)
9976                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9977                                 else
9978                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9979                                 // then apply the texture to it
9980                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9981                                 R_Mesh_TexBind(0, layer->texture);
9982                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9983                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9984                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9985                                 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);
9986                         }
9987                         else
9988                         {
9989                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
9990                                 R_Mesh_TexBind(0, layer->texture);
9991                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9992                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9993                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9994                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9995                                         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);
9996                                 else
9997                                         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);
9998                         }
9999                         break;
10000                 case TEXTURELAYERTYPE_TEXTURE:
10001                         // singletexture unlit texture with transparency support
10002                         R_Mesh_TexBind(0, layer->texture);
10003                         R_Mesh_TexMatrix(0, &layer->texmatrix);
10004                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10005                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10006                         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);
10007                         break;
10008                 case TEXTURELAYERTYPE_FOG:
10009                         // singletexture fogging
10010                         if (layer->texture)
10011                         {
10012                                 R_Mesh_TexBind(0, layer->texture);
10013                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10014                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10015                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10016                         }
10017                         else
10018                         {
10019                                 R_Mesh_TexBind(0, 0);
10020                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10021                         }
10022                         // generate a color array for the fog pass
10023                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10024                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10025                         RSurf_DrawBatch();
10026                         break;
10027                 default:
10028                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10029                 }
10030         }
10031         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10032         {
10033                 GL_DepthFunc(GL_LEQUAL);
10034                 GL_AlphaTest(false);
10035         }
10036 }
10037
10038 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10039 {
10040         int vi;
10041         int j;
10042         r_vertexgeneric_t *batchvertex;
10043         float c[4];
10044
10045 //      R_Mesh_ResetTextureState();
10046         R_SetupShader_Generic_NoTexture(false, false);
10047
10048         if(rsurface.texture && rsurface.texture->currentskinframe)
10049         {
10050                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10051                 c[3] *= rsurface.texture->currentalpha;
10052         }
10053         else
10054         {
10055                 c[0] = 1;
10056                 c[1] = 0;
10057                 c[2] = 1;
10058                 c[3] = 1;
10059         }
10060
10061         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10062         {
10063                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10064                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10065                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10066         }
10067
10068         // brighten it up (as texture value 127 means "unlit")
10069         c[0] *= 2 * r_refdef.view.colorscale;
10070         c[1] *= 2 * r_refdef.view.colorscale;
10071         c[2] *= 2 * r_refdef.view.colorscale;
10072
10073         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10074                 c[3] *= r_wateralpha.value;
10075
10076         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10077         {
10078                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10079                 GL_DepthMask(false);
10080         }
10081         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10082         {
10083                 GL_BlendFunc(GL_ONE, GL_ONE);
10084                 GL_DepthMask(false);
10085         }
10086         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10087         {
10088                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10089                 GL_DepthMask(false);
10090         }
10091         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10092         {
10093                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10094                 GL_DepthMask(false);
10095         }
10096         else
10097         {
10098                 GL_BlendFunc(GL_ONE, GL_ZERO);
10099                 GL_DepthMask(writedepth);
10100         }
10101
10102         if (r_showsurfaces.integer == 3)
10103         {
10104                 rsurface.passcolor4f = NULL;
10105
10106                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10107                 {
10108                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10109
10110                         rsurface.passcolor4f = NULL;
10111                         rsurface.passcolor4f_vertexbuffer = 0;
10112                         rsurface.passcolor4f_bufferoffset = 0;
10113                 }
10114                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10115                 {
10116                         qboolean applycolor = true;
10117                         float one = 1.0;
10118
10119                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10120
10121                         r_refdef.lightmapintensity = 1;
10122                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10123                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10124                 }
10125                 else if (FAKELIGHT_ENABLED)
10126                 {
10127                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10128
10129                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10130                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10131                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10132                 }
10133                 else
10134                 {
10135                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10136
10137                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10138                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10139                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10140                 }
10141
10142                 if(!rsurface.passcolor4f)
10143                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10144
10145                 RSurf_DrawBatch_GL11_ApplyAmbient();
10146                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10147                 if(r_refdef.fogenabled)
10148                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10149                 RSurf_DrawBatch_GL11_ClampColor();
10150
10151                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10152                 R_SetupShader_Generic_NoTexture(false, false);
10153                 RSurf_DrawBatch();
10154         }
10155         else if (!r_refdef.view.showdebug)
10156         {
10157                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10158                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10159                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10160                 {
10161                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10162                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10163                 }
10164                 R_Mesh_PrepareVertices_Generic_Unlock();
10165                 RSurf_DrawBatch();
10166         }
10167         else if (r_showsurfaces.integer == 4)
10168         {
10169                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10170                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10171                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10172                 {
10173                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10174                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10175                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10176                 }
10177                 R_Mesh_PrepareVertices_Generic_Unlock();
10178                 RSurf_DrawBatch();
10179         }
10180         else if (r_showsurfaces.integer == 2)
10181         {
10182                 const int *e;
10183                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10184                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10185                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10186                 {
10187                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10188                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10189                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10190                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10191                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10192                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10193                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10194                 }
10195                 R_Mesh_PrepareVertices_Generic_Unlock();
10196                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10197         }
10198         else
10199         {
10200                 int texturesurfaceindex;
10201                 int k;
10202                 const msurface_t *surface;
10203                 float surfacecolor4f[4];
10204                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10205                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10206                 vi = 0;
10207                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10208                 {
10209                         surface = texturesurfacelist[texturesurfaceindex];
10210                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10211                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10212                         for (j = 0;j < surface->num_vertices;j++)
10213                         {
10214                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10215                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10216                                 vi++;
10217                         }
10218                 }
10219                 R_Mesh_PrepareVertices_Generic_Unlock();
10220                 RSurf_DrawBatch();
10221         }
10222 }
10223
10224 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10225 {
10226         CHECKGLERROR
10227         RSurf_SetupDepthAndCulling();
10228         if (r_showsurfaces.integer)
10229         {
10230                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10231                 return;
10232         }
10233         switch (vid.renderpath)
10234         {
10235         case RENDERPATH_GL20:
10236         case RENDERPATH_D3D9:
10237         case RENDERPATH_D3D10:
10238         case RENDERPATH_D3D11:
10239         case RENDERPATH_SOFT:
10240         case RENDERPATH_GLES2:
10241                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10242                 break;
10243         case RENDERPATH_GL13:
10244         case RENDERPATH_GLES1:
10245                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10246                 break;
10247         case RENDERPATH_GL11:
10248                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10249                 break;
10250         }
10251         CHECKGLERROR
10252 }
10253
10254 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10255 {
10256         CHECKGLERROR
10257         RSurf_SetupDepthAndCulling();
10258         if (r_showsurfaces.integer)
10259         {
10260                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10261                 return;
10262         }
10263         switch (vid.renderpath)
10264         {
10265         case RENDERPATH_GL20:
10266         case RENDERPATH_D3D9:
10267         case RENDERPATH_D3D10:
10268         case RENDERPATH_D3D11:
10269         case RENDERPATH_SOFT:
10270         case RENDERPATH_GLES2:
10271                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10272                 break;
10273         case RENDERPATH_GL13:
10274         case RENDERPATH_GLES1:
10275                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10276                 break;
10277         case RENDERPATH_GL11:
10278                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10279                 break;
10280         }
10281         CHECKGLERROR
10282 }
10283
10284 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10285 {
10286         int i, j;
10287         int texturenumsurfaces, endsurface;
10288         texture_t *texture;
10289         const msurface_t *surface;
10290         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10291
10292         // if the model is static it doesn't matter what value we give for
10293         // wantnormals and wanttangents, so this logic uses only rules applicable
10294         // to a model, knowing that they are meaningless otherwise
10295         if (ent == r_refdef.scene.worldentity)
10296                 RSurf_ActiveWorldEntity();
10297         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10298                 RSurf_ActiveModelEntity(ent, false, false, false);
10299         else
10300         {
10301                 switch (vid.renderpath)
10302                 {
10303                 case RENDERPATH_GL20:
10304                 case RENDERPATH_D3D9:
10305                 case RENDERPATH_D3D10:
10306                 case RENDERPATH_D3D11:
10307                 case RENDERPATH_SOFT:
10308                 case RENDERPATH_GLES2:
10309                         RSurf_ActiveModelEntity(ent, true, true, false);
10310                         break;
10311                 case RENDERPATH_GL11:
10312                 case RENDERPATH_GL13:
10313                 case RENDERPATH_GLES1:
10314                         RSurf_ActiveModelEntity(ent, true, false, false);
10315                         break;
10316                 }
10317         }
10318
10319         if (r_transparentdepthmasking.integer)
10320         {
10321                 qboolean setup = false;
10322                 for (i = 0;i < numsurfaces;i = j)
10323                 {
10324                         j = i + 1;
10325                         surface = rsurface.modelsurfaces + surfacelist[i];
10326                         texture = surface->texture;
10327                         rsurface.texture = R_GetCurrentTexture(texture);
10328                         rsurface.lightmaptexture = NULL;
10329                         rsurface.deluxemaptexture = NULL;
10330                         rsurface.uselightmaptexture = false;
10331                         // scan ahead until we find a different texture
10332                         endsurface = min(i + 1024, numsurfaces);
10333                         texturenumsurfaces = 0;
10334                         texturesurfacelist[texturenumsurfaces++] = surface;
10335                         for (;j < endsurface;j++)
10336                         {
10337                                 surface = rsurface.modelsurfaces + surfacelist[j];
10338                                 if (texture != surface->texture)
10339                                         break;
10340                                 texturesurfacelist[texturenumsurfaces++] = surface;
10341                         }
10342                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10343                                 continue;
10344                         // render the range of surfaces as depth
10345                         if (!setup)
10346                         {
10347                                 setup = true;
10348                                 GL_ColorMask(0,0,0,0);
10349                                 GL_Color(1,1,1,1);
10350                                 GL_DepthTest(true);
10351                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10352                                 GL_DepthMask(true);
10353 //                              R_Mesh_ResetTextureState();
10354                                 R_SetupShader_DepthOrShadow(false, false);
10355                         }
10356                         RSurf_SetupDepthAndCulling();
10357                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10358                         if (rsurface.batchvertex3fbuffer)
10359                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10360                         else
10361                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10362                         RSurf_DrawBatch();
10363                 }
10364                 if (setup)
10365                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10366         }
10367
10368         for (i = 0;i < numsurfaces;i = j)
10369         {
10370                 j = i + 1;
10371                 surface = rsurface.modelsurfaces + surfacelist[i];
10372                 texture = surface->texture;
10373                 rsurface.texture = R_GetCurrentTexture(texture);
10374                 // scan ahead until we find a different texture
10375                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10376                 texturenumsurfaces = 0;
10377                 texturesurfacelist[texturenumsurfaces++] = surface;
10378                 if(FAKELIGHT_ENABLED)
10379                 {
10380                         rsurface.lightmaptexture = NULL;
10381                         rsurface.deluxemaptexture = NULL;
10382                         rsurface.uselightmaptexture = false;
10383                         for (;j < endsurface;j++)
10384                         {
10385                                 surface = rsurface.modelsurfaces + surfacelist[j];
10386                                 if (texture != surface->texture)
10387                                         break;
10388                                 texturesurfacelist[texturenumsurfaces++] = surface;
10389                         }
10390                 }
10391                 else
10392                 {
10393                         rsurface.lightmaptexture = surface->lightmaptexture;
10394                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10395                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10396                         for (;j < endsurface;j++)
10397                         {
10398                                 surface = rsurface.modelsurfaces + surfacelist[j];
10399                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10400                                         break;
10401                                 texturesurfacelist[texturenumsurfaces++] = surface;
10402                         }
10403                 }
10404                 // render the range of surfaces
10405                 if (ent == r_refdef.scene.worldentity)
10406                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10407                 else
10408                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10409         }
10410         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10411 }
10412
10413 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, const entity_render_t *queueentity)
10414 {
10415         // transparent surfaces get pushed off into the transparent queue
10416         int surfacelistindex;
10417         const msurface_t *surface;
10418         vec3_t tempcenter, center;
10419         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10420         {
10421                 surface = texturesurfacelist[surfacelistindex];
10422                 tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10423                 tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10424                 tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10425                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10426                 if (queueentity->transparent_offset) // transparent offset
10427                 {
10428                         center[0] += r_refdef.view.forward[0]*queueentity->transparent_offset;
10429                         center[1] += r_refdef.view.forward[1]*queueentity->transparent_offset;
10430                         center[2] += r_refdef.view.forward[2]*queueentity->transparent_offset;
10431                 }
10432                 R_MeshQueue_AddTransparent(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST ? r_refdef.view.origin : center, R_DrawSurface_TransparentCallback, queueentity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10433         }
10434 }
10435
10436 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10437 {
10438         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10439                 return;
10440         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10441                 return;
10442         RSurf_SetupDepthAndCulling();
10443         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10444         if (rsurface.batchvertex3fbuffer)
10445                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10446         else
10447                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10448         RSurf_DrawBatch();
10449 }
10450
10451 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10452 {
10453         const entity_render_t *queueentity = r_refdef.scene.worldentity;
10454         CHECKGLERROR
10455         if (depthonly)
10456                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10457         else if (prepass)
10458         {
10459                 if (!rsurface.texture->currentnumlayers)
10460                         return;
10461                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10462                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10463                 else
10464                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10465         }
10466         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10467                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10468         else if (!rsurface.texture->currentnumlayers)
10469                 return;
10470         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10471         {
10472                 // in the deferred case, transparent surfaces were queued during prepass
10473                 if (!r_shadow_usingdeferredprepass)
10474                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10475         }
10476         else
10477         {
10478                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10479                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10480         }
10481         CHECKGLERROR
10482 }
10483
10484 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10485 {
10486         int i, j;
10487         texture_t *texture;
10488         R_FrameData_SetMark();
10489         // break the surface list down into batches by texture and use of lightmapping
10490         for (i = 0;i < numsurfaces;i = j)
10491         {
10492                 j = i + 1;
10493                 // texture is the base texture pointer, rsurface.texture is the
10494                 // current frame/skin the texture is directing us to use (for example
10495                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10496                 // use skin 1 instead)
10497                 texture = surfacelist[i]->texture;
10498                 rsurface.texture = R_GetCurrentTexture(texture);
10499                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10500                 {
10501                         // if this texture is not the kind we want, skip ahead to the next one
10502                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10503                                 ;
10504                         continue;
10505                 }
10506                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10507                 {
10508                         rsurface.lightmaptexture = NULL;
10509                         rsurface.deluxemaptexture = NULL;
10510                         rsurface.uselightmaptexture = false;
10511                         // simply scan ahead until we find a different texture or lightmap state
10512                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10513                                 ;
10514                 }
10515                 else
10516                 {
10517                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10518                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10519                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10520                         // simply scan ahead until we find a different texture or lightmap state
10521                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10522                                 ;
10523                 }
10524                 // render the range of surfaces
10525                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10526         }
10527         R_FrameData_ReturnToMark();
10528 }
10529
10530 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, const entity_render_t *queueentity, qboolean prepass)
10531 {
10532         CHECKGLERROR
10533         if (depthonly)
10534                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10535         else if (prepass)
10536         {
10537                 if (!rsurface.texture->currentnumlayers)
10538                         return;
10539                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10540                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10541                 else
10542                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10543         }
10544         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10545                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10546         else if (!rsurface.texture->currentnumlayers)
10547                 return;
10548         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))) && queueentity)
10549         {
10550                 // in the deferred case, transparent surfaces were queued during prepass
10551                 if (!r_shadow_usingdeferredprepass)
10552                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist, queueentity);
10553         }
10554         else
10555         {
10556                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10557                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10558         }
10559         CHECKGLERROR
10560 }
10561
10562 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10563 {
10564         int i, j;
10565         texture_t *texture;
10566         R_FrameData_SetMark();
10567         // break the surface list down into batches by texture and use of lightmapping
10568         for (i = 0;i < numsurfaces;i = j)
10569         {
10570                 j = i + 1;
10571                 // texture is the base texture pointer, rsurface.texture is the
10572                 // current frame/skin the texture is directing us to use (for example
10573                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10574                 // use skin 1 instead)
10575                 texture = surfacelist[i]->texture;
10576                 rsurface.texture = R_GetCurrentTexture(texture);
10577                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10578                 {
10579                         // if this texture is not the kind we want, skip ahead to the next one
10580                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10581                                 ;
10582                         continue;
10583                 }
10584                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10585                 {
10586                         rsurface.lightmaptexture = NULL;
10587                         rsurface.deluxemaptexture = NULL;
10588                         rsurface.uselightmaptexture = false;
10589                         // simply scan ahead until we find a different texture or lightmap state
10590                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10591                                 ;
10592                 }
10593                 else
10594                 {
10595                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10596                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10597                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10598                         // simply scan ahead until we find a different texture or lightmap state
10599                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10600                                 ;
10601                 }
10602                 // render the range of surfaces
10603                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, ent, prepass);
10604         }
10605         R_FrameData_ReturnToMark();
10606 }
10607
10608 float locboxvertex3f[6*4*3] =
10609 {
10610         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10611         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10612         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10613         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10614         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10615         1,0,0, 0,0,0, 0,1,0, 1,1,0
10616 };
10617
10618 unsigned short locboxelements[6*2*3] =
10619 {
10620          0, 1, 2, 0, 2, 3,
10621          4, 5, 6, 4, 6, 7,
10622          8, 9,10, 8,10,11,
10623         12,13,14, 12,14,15,
10624         16,17,18, 16,18,19,
10625         20,21,22, 20,22,23
10626 };
10627
10628 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10629 {
10630         int i, j;
10631         cl_locnode_t *loc = (cl_locnode_t *)ent;
10632         vec3_t mins, size;
10633         float vertex3f[6*4*3];
10634         CHECKGLERROR
10635         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10636         GL_DepthMask(false);
10637         GL_DepthRange(0, 1);
10638         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10639         GL_DepthTest(true);
10640         GL_CullFace(GL_NONE);
10641         R_EntityMatrix(&identitymatrix);
10642
10643 //      R_Mesh_ResetTextureState();
10644
10645         i = surfacelist[0];
10646         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10647                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10648                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10649                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10650
10651         if (VectorCompare(loc->mins, loc->maxs))
10652         {
10653                 VectorSet(size, 2, 2, 2);
10654                 VectorMA(loc->mins, -0.5f, size, mins);
10655         }
10656         else
10657         {
10658                 VectorCopy(loc->mins, mins);
10659                 VectorSubtract(loc->maxs, loc->mins, size);
10660         }
10661
10662         for (i = 0;i < 6*4*3;)
10663                 for (j = 0;j < 3;j++, i++)
10664                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10665
10666         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10667         R_SetupShader_Generic_NoTexture(false, false);
10668         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10669 }
10670
10671 void R_DrawLocs(void)
10672 {
10673         int index;
10674         cl_locnode_t *loc, *nearestloc;
10675         vec3_t center;
10676         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10677         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10678         {
10679                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10680                 R_MeshQueue_AddTransparent(center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10681         }
10682 }
10683
10684 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10685 {
10686         if (decalsystem->decals)
10687                 Mem_Free(decalsystem->decals);
10688         memset(decalsystem, 0, sizeof(*decalsystem));
10689 }
10690
10691 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)
10692 {
10693         tridecal_t *decal;
10694         tridecal_t *decals;
10695         int i;
10696
10697         // expand or initialize the system
10698         if (decalsystem->maxdecals <= decalsystem->numdecals)
10699         {
10700                 decalsystem_t old = *decalsystem;
10701                 qboolean useshortelements;
10702                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10703                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10704                 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)));
10705                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10706                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10707                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10708                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10709                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10710                 if (decalsystem->numdecals)
10711                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10712                 if (old.decals)
10713                         Mem_Free(old.decals);
10714                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10715                         decalsystem->element3i[i] = i;
10716                 if (useshortelements)
10717                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10718                                 decalsystem->element3s[i] = i;
10719         }
10720
10721         // grab a decal and search for another free slot for the next one
10722         decals = decalsystem->decals;
10723         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10724         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10725                 ;
10726         decalsystem->freedecal = i;
10727         if (decalsystem->numdecals <= i)
10728                 decalsystem->numdecals = i + 1;
10729
10730         // initialize the decal
10731         decal->lived = 0;
10732         decal->triangleindex = triangleindex;
10733         decal->surfaceindex = surfaceindex;
10734         decal->decalsequence = decalsequence;
10735         decal->color4f[0][0] = c0[0];
10736         decal->color4f[0][1] = c0[1];
10737         decal->color4f[0][2] = c0[2];
10738         decal->color4f[0][3] = 1;
10739         decal->color4f[1][0] = c1[0];
10740         decal->color4f[1][1] = c1[1];
10741         decal->color4f[1][2] = c1[2];
10742         decal->color4f[1][3] = 1;
10743         decal->color4f[2][0] = c2[0];
10744         decal->color4f[2][1] = c2[1];
10745         decal->color4f[2][2] = c2[2];
10746         decal->color4f[2][3] = 1;
10747         decal->vertex3f[0][0] = v0[0];
10748         decal->vertex3f[0][1] = v0[1];
10749         decal->vertex3f[0][2] = v0[2];
10750         decal->vertex3f[1][0] = v1[0];
10751         decal->vertex3f[1][1] = v1[1];
10752         decal->vertex3f[1][2] = v1[2];
10753         decal->vertex3f[2][0] = v2[0];
10754         decal->vertex3f[2][1] = v2[1];
10755         decal->vertex3f[2][2] = v2[2];
10756         decal->texcoord2f[0][0] = t0[0];
10757         decal->texcoord2f[0][1] = t0[1];
10758         decal->texcoord2f[1][0] = t1[0];
10759         decal->texcoord2f[1][1] = t1[1];
10760         decal->texcoord2f[2][0] = t2[0];
10761         decal->texcoord2f[2][1] = t2[1];
10762         TriangleNormal(v0, v1, v2, decal->plane);
10763         VectorNormalize(decal->plane);
10764         decal->plane[3] = DotProduct(v0, decal->plane);
10765 }
10766
10767 extern cvar_t cl_decals_bias;
10768 extern cvar_t cl_decals_models;
10769 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10770 // baseparms, parms, temps
10771 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)
10772 {
10773         int cornerindex;
10774         int index;
10775         float v[9][3];
10776         const float *vertex3f;
10777         const float *normal3f;
10778         int numpoints;
10779         float points[2][9][3];
10780         float temp[3];
10781         float tc[9][2];
10782         float f;
10783         float c[9][4];
10784         const int *e;
10785
10786         e = rsurface.modelelement3i + 3*triangleindex;
10787
10788         vertex3f = rsurface.modelvertex3f;
10789         normal3f = rsurface.modelnormal3f;
10790
10791         if (normal3f)
10792         {
10793                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10794                 {
10795                         index = 3*e[cornerindex];
10796                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10797                 }
10798         }
10799         else
10800         {
10801                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10802                 {
10803                         index = 3*e[cornerindex];
10804                         VectorCopy(vertex3f + index, v[cornerindex]);
10805                 }
10806         }
10807
10808         // cull backfaces
10809         //TriangleNormal(v[0], v[1], v[2], normal);
10810         //if (DotProduct(normal, localnormal) < 0.0f)
10811         //      continue;
10812         // clip by each of the box planes formed from the projection matrix
10813         // if anything survives, we emit the decal
10814         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]);
10815         if (numpoints < 3)
10816                 return;
10817         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]);
10818         if (numpoints < 3)
10819                 return;
10820         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]);
10821         if (numpoints < 3)
10822                 return;
10823         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]);
10824         if (numpoints < 3)
10825                 return;
10826         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]);
10827         if (numpoints < 3)
10828                 return;
10829         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]);
10830         if (numpoints < 3)
10831                 return;
10832         // some part of the triangle survived, so we have to accept it...
10833         if (dynamic)
10834         {
10835                 // dynamic always uses the original triangle
10836                 numpoints = 3;
10837                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10838                 {
10839                         index = 3*e[cornerindex];
10840                         VectorCopy(vertex3f + index, v[cornerindex]);
10841                 }
10842         }
10843         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10844         {
10845                 // convert vertex positions to texcoords
10846                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10847                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10848                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10849                 // calculate distance fade from the projection origin
10850                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10851                 f = bound(0.0f, f, 1.0f);
10852                 c[cornerindex][0] = r * f;
10853                 c[cornerindex][1] = g * f;
10854                 c[cornerindex][2] = b * f;
10855                 c[cornerindex][3] = 1.0f;
10856                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10857         }
10858         if (dynamic)
10859                 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);
10860         else
10861                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10862                         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);
10863 }
10864 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)
10865 {
10866         matrix4x4_t projection;
10867         decalsystem_t *decalsystem;
10868         qboolean dynamic;
10869         dp_model_t *model;
10870         const msurface_t *surface;
10871         const msurface_t *surfaces;
10872         const int *surfacelist;
10873         const texture_t *texture;
10874         int numtriangles;
10875         int numsurfacelist;
10876         int surfacelistindex;
10877         int surfaceindex;
10878         int triangleindex;
10879         float localorigin[3];
10880         float localnormal[3];
10881         float localmins[3];
10882         float localmaxs[3];
10883         float localsize;
10884         //float normal[3];
10885         float planes[6][4];
10886         float angles[3];
10887         bih_t *bih;
10888         int bih_triangles_count;
10889         int bih_triangles[256];
10890         int bih_surfaces[256];
10891
10892         decalsystem = &ent->decalsystem;
10893         model = ent->model;
10894         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10895         {
10896                 R_DecalSystem_Reset(&ent->decalsystem);
10897                 return;
10898         }
10899
10900         if (!model->brush.data_leafs && !cl_decals_models.integer)
10901         {
10902                 if (decalsystem->model)
10903                         R_DecalSystem_Reset(decalsystem);
10904                 return;
10905         }
10906
10907         if (decalsystem->model != model)
10908                 R_DecalSystem_Reset(decalsystem);
10909         decalsystem->model = model;
10910
10911         RSurf_ActiveModelEntity(ent, true, false, false);
10912
10913         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10914         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10915         VectorNormalize(localnormal);
10916         localsize = worldsize*rsurface.inversematrixscale;
10917         localmins[0] = localorigin[0] - localsize;
10918         localmins[1] = localorigin[1] - localsize;
10919         localmins[2] = localorigin[2] - localsize;
10920         localmaxs[0] = localorigin[0] + localsize;
10921         localmaxs[1] = localorigin[1] + localsize;
10922         localmaxs[2] = localorigin[2] + localsize;
10923
10924         //VectorCopy(localnormal, planes[4]);
10925         //VectorVectors(planes[4], planes[2], planes[0]);
10926         AnglesFromVectors(angles, localnormal, NULL, false);
10927         AngleVectors(angles, planes[0], planes[2], planes[4]);
10928         VectorNegate(planes[0], planes[1]);
10929         VectorNegate(planes[2], planes[3]);
10930         VectorNegate(planes[4], planes[5]);
10931         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10932         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10933         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10934         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10935         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10936         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10937
10938 #if 1
10939 // works
10940 {
10941         matrix4x4_t forwardprojection;
10942         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10943         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10944 }
10945 #else
10946 // broken
10947 {
10948         float projectionvector[4][3];
10949         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10950         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10951         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10952         projectionvector[0][0] = planes[0][0] * ilocalsize;
10953         projectionvector[0][1] = planes[1][0] * ilocalsize;
10954         projectionvector[0][2] = planes[2][0] * ilocalsize;
10955         projectionvector[1][0] = planes[0][1] * ilocalsize;
10956         projectionvector[1][1] = planes[1][1] * ilocalsize;
10957         projectionvector[1][2] = planes[2][1] * ilocalsize;
10958         projectionvector[2][0] = planes[0][2] * ilocalsize;
10959         projectionvector[2][1] = planes[1][2] * ilocalsize;
10960         projectionvector[2][2] = planes[2][2] * ilocalsize;
10961         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10962         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10963         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10964         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10965 }
10966 #endif
10967
10968         dynamic = model->surfmesh.isanimated;
10969         numsurfacelist = model->nummodelsurfaces;
10970         surfacelist = model->sortedmodelsurfaces;
10971         surfaces = model->data_surfaces;
10972
10973         bih = NULL;
10974         bih_triangles_count = -1;
10975         if(!dynamic)
10976         {
10977                 if(model->render_bih.numleafs)
10978                         bih = &model->render_bih;
10979                 else if(model->collision_bih.numleafs)
10980                         bih = &model->collision_bih;
10981         }
10982         if(bih)
10983                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
10984         if(bih_triangles_count == 0)
10985                 return;
10986         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
10987                 return;
10988         if(bih_triangles_count > 0)
10989         {
10990                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
10991                 {
10992                         surfaceindex = bih_surfaces[triangleindex];
10993                         surface = surfaces + surfaceindex;
10994                         texture = surface->texture;
10995                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
10996                                 continue;
10997                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
10998                                 continue;
10999                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11000                 }
11001         }
11002         else
11003         {
11004                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11005                 {
11006                         surfaceindex = surfacelist[surfacelistindex];
11007                         surface = surfaces + surfaceindex;
11008                         // check cull box first because it rejects more than any other check
11009                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11010                                 continue;
11011                         // skip transparent surfaces
11012                         texture = surface->texture;
11013                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11014                                 continue;
11015                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11016                                 continue;
11017                         numtriangles = surface->num_triangles;
11018                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11019                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11020                 }
11021         }
11022 }
11023
11024 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11025 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)
11026 {
11027         int renderentityindex;
11028         float worldmins[3];
11029         float worldmaxs[3];
11030         entity_render_t *ent;
11031
11032         if (!cl_decals_newsystem.integer)
11033                 return;
11034
11035         worldmins[0] = worldorigin[0] - worldsize;
11036         worldmins[1] = worldorigin[1] - worldsize;
11037         worldmins[2] = worldorigin[2] - worldsize;
11038         worldmaxs[0] = worldorigin[0] + worldsize;
11039         worldmaxs[1] = worldorigin[1] + worldsize;
11040         worldmaxs[2] = worldorigin[2] + worldsize;
11041
11042         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11043
11044         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11045         {
11046                 ent = r_refdef.scene.entities[renderentityindex];
11047                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11048                         continue;
11049
11050                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11051         }
11052 }
11053
11054 typedef struct r_decalsystem_splatqueue_s
11055 {
11056         vec3_t worldorigin;
11057         vec3_t worldnormal;
11058         float color[4];
11059         float tcrange[4];
11060         float worldsize;
11061         int decalsequence;
11062 }
11063 r_decalsystem_splatqueue_t;
11064
11065 int r_decalsystem_numqueued = 0;
11066 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11067
11068 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)
11069 {
11070         r_decalsystem_splatqueue_t *queue;
11071
11072         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11073                 return;
11074
11075         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11076         VectorCopy(worldorigin, queue->worldorigin);
11077         VectorCopy(worldnormal, queue->worldnormal);
11078         Vector4Set(queue->color, r, g, b, a);
11079         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11080         queue->worldsize = worldsize;
11081         queue->decalsequence = cl.decalsequence++;
11082 }
11083
11084 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11085 {
11086         int i;
11087         r_decalsystem_splatqueue_t *queue;
11088
11089         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11090                 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);
11091         r_decalsystem_numqueued = 0;
11092 }
11093
11094 extern cvar_t cl_decals_max;
11095 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11096 {
11097         int i;
11098         decalsystem_t *decalsystem = &ent->decalsystem;
11099         int numdecals;
11100         int killsequence;
11101         tridecal_t *decal;
11102         float frametime;
11103         float lifetime;
11104
11105         if (!decalsystem->numdecals)
11106                 return;
11107
11108         if (r_showsurfaces.integer)
11109                 return;
11110
11111         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11112         {
11113                 R_DecalSystem_Reset(decalsystem);
11114                 return;
11115         }
11116
11117         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11118         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11119
11120         if (decalsystem->lastupdatetime)
11121                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11122         else
11123                 frametime = 0;
11124         decalsystem->lastupdatetime = r_refdef.scene.time;
11125         decal = decalsystem->decals;
11126         numdecals = decalsystem->numdecals;
11127
11128         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11129         {
11130                 if (decal->color4f[0][3])
11131                 {
11132                         decal->lived += frametime;
11133                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11134                         {
11135                                 memset(decal, 0, sizeof(*decal));
11136                                 if (decalsystem->freedecal > i)
11137                                         decalsystem->freedecal = i;
11138                         }
11139                 }
11140         }
11141         decal = decalsystem->decals;
11142         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11143                 numdecals--;
11144
11145         // collapse the array by shuffling the tail decals into the gaps
11146         for (;;)
11147         {
11148                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11149                         decalsystem->freedecal++;
11150                 if (decalsystem->freedecal == numdecals)
11151                         break;
11152                 decal[decalsystem->freedecal] = decal[--numdecals];
11153         }
11154
11155         decalsystem->numdecals = numdecals;
11156
11157         if (numdecals <= 0)
11158         {
11159                 // if there are no decals left, reset decalsystem
11160                 R_DecalSystem_Reset(decalsystem);
11161         }
11162 }
11163
11164 extern skinframe_t *decalskinframe;
11165 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11166 {
11167         int i;
11168         decalsystem_t *decalsystem = &ent->decalsystem;
11169         int numdecals;
11170         tridecal_t *decal;
11171         float faderate;
11172         float alpha;
11173         float *v3f;
11174         float *c4f;
11175         float *t2f;
11176         const int *e;
11177         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11178         int numtris = 0;
11179
11180         numdecals = decalsystem->numdecals;
11181         if (!numdecals)
11182                 return;
11183
11184         if (r_showsurfaces.integer)
11185                 return;
11186
11187         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11188         {
11189                 R_DecalSystem_Reset(decalsystem);
11190                 return;
11191         }
11192
11193         // if the model is static it doesn't matter what value we give for
11194         // wantnormals and wanttangents, so this logic uses only rules applicable
11195         // to a model, knowing that they are meaningless otherwise
11196         if (ent == r_refdef.scene.worldentity)
11197                 RSurf_ActiveWorldEntity();
11198         else
11199                 RSurf_ActiveModelEntity(ent, false, false, false);
11200
11201         decalsystem->lastupdatetime = r_refdef.scene.time;
11202         decal = decalsystem->decals;
11203
11204         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11205
11206         // update vertex positions for animated models
11207         v3f = decalsystem->vertex3f;
11208         c4f = decalsystem->color4f;
11209         t2f = decalsystem->texcoord2f;
11210         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11211         {
11212                 if (!decal->color4f[0][3])
11213                         continue;
11214
11215                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11216                         continue;
11217
11218                 // skip backfaces
11219                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11220                         continue;
11221
11222                 // update color values for fading decals
11223                 if (decal->lived >= cl_decals_time.value)
11224                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11225                 else
11226                         alpha = 1.0f;
11227
11228                 c4f[ 0] = decal->color4f[0][0] * alpha;
11229                 c4f[ 1] = decal->color4f[0][1] * alpha;
11230                 c4f[ 2] = decal->color4f[0][2] * alpha;
11231                 c4f[ 3] = 1;
11232                 c4f[ 4] = decal->color4f[1][0] * alpha;
11233                 c4f[ 5] = decal->color4f[1][1] * alpha;
11234                 c4f[ 6] = decal->color4f[1][2] * alpha;
11235                 c4f[ 7] = 1;
11236                 c4f[ 8] = decal->color4f[2][0] * alpha;
11237                 c4f[ 9] = decal->color4f[2][1] * alpha;
11238                 c4f[10] = decal->color4f[2][2] * alpha;
11239                 c4f[11] = 1;
11240
11241                 t2f[0] = decal->texcoord2f[0][0];
11242                 t2f[1] = decal->texcoord2f[0][1];
11243                 t2f[2] = decal->texcoord2f[1][0];
11244                 t2f[3] = decal->texcoord2f[1][1];
11245                 t2f[4] = decal->texcoord2f[2][0];
11246                 t2f[5] = decal->texcoord2f[2][1];
11247
11248                 // update vertex positions for animated models
11249                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11250                 {
11251                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11252                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11253                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11254                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11255                 }
11256                 else
11257                 {
11258                         VectorCopy(decal->vertex3f[0], v3f);
11259                         VectorCopy(decal->vertex3f[1], v3f + 3);
11260                         VectorCopy(decal->vertex3f[2], v3f + 6);
11261                 }
11262
11263                 if (r_refdef.fogenabled)
11264                 {
11265                         alpha = RSurf_FogVertex(v3f);
11266                         VectorScale(c4f, alpha, c4f);
11267                         alpha = RSurf_FogVertex(v3f + 3);
11268                         VectorScale(c4f + 4, alpha, c4f + 4);
11269                         alpha = RSurf_FogVertex(v3f + 6);
11270                         VectorScale(c4f + 8, alpha, c4f + 8);
11271                 }
11272
11273                 v3f += 9;
11274                 c4f += 12;
11275                 t2f += 6;
11276                 numtris++;
11277         }
11278
11279         if (numtris > 0)
11280         {
11281                 r_refdef.stats.drawndecals += numtris;
11282
11283                 // now render the decals all at once
11284                 // (this assumes they all use one particle font texture!)
11285                 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);
11286 //              R_Mesh_ResetTextureState();
11287                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11288                 GL_DepthMask(false);
11289                 GL_DepthRange(0, 1);
11290                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11291                 GL_DepthTest(true);
11292                 GL_CullFace(GL_NONE);
11293                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11294                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11295                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11296         }
11297 }
11298
11299 static void R_DrawModelDecals(void)
11300 {
11301         int i, numdecals;
11302
11303         // fade faster when there are too many decals
11304         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11305         for (i = 0;i < r_refdef.scene.numentities;i++)
11306                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11307
11308         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11309         for (i = 0;i < r_refdef.scene.numentities;i++)
11310                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11311                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11312
11313         R_DecalSystem_ApplySplatEntitiesQueue();
11314
11315         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11316         for (i = 0;i < r_refdef.scene.numentities;i++)
11317                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11318
11319         r_refdef.stats.totaldecals += numdecals;
11320
11321         if (r_showsurfaces.integer)
11322                 return;
11323
11324         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11325
11326         for (i = 0;i < r_refdef.scene.numentities;i++)
11327         {
11328                 if (!r_refdef.viewcache.entityvisible[i])
11329                         continue;
11330                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11331                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11332         }
11333 }
11334
11335 extern cvar_t mod_collision_bih;
11336 static void R_DrawDebugModel(void)
11337 {
11338         entity_render_t *ent = rsurface.entity;
11339         int i, j, k, l, flagsmask;
11340         const msurface_t *surface;
11341         dp_model_t *model = ent->model;
11342         vec3_t v;
11343
11344         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11345                 return;
11346
11347         if (r_showoverdraw.value > 0)
11348         {
11349                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11350                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11351                 R_SetupShader_Generic_NoTexture(false, false);
11352                 GL_DepthTest(false);
11353                 GL_DepthMask(false);
11354                 GL_DepthRange(0, 1);
11355                 GL_BlendFunc(GL_ONE, GL_ONE);
11356                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11357                 {
11358                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11359                                 continue;
11360                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11361                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11362                         {
11363                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11364                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11365                                 if (!rsurface.texture->currentlayers->depthmask)
11366                                         GL_Color(c, 0, 0, 1.0f);
11367                                 else if (ent == r_refdef.scene.worldentity)
11368                                         GL_Color(c, c, c, 1.0f);
11369                                 else
11370                                         GL_Color(0, c, 0, 1.0f);
11371                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11372                                 RSurf_DrawBatch();
11373                         }
11374                 }
11375                 rsurface.texture = NULL;
11376         }
11377
11378         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11379
11380 //      R_Mesh_ResetTextureState();
11381         R_SetupShader_Generic_NoTexture(false, false);
11382         GL_DepthRange(0, 1);
11383         GL_DepthTest(!r_showdisabledepthtest.integer);
11384         GL_DepthMask(false);
11385         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11386
11387         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11388         {
11389                 int triangleindex;
11390                 int bihleafindex;
11391                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11392                 const q3mbrush_t *brush;
11393                 const bih_t *bih = &model->collision_bih;
11394                 const bih_leaf_t *bihleaf;
11395                 float vertex3f[3][3];
11396                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11397                 cullbox = false;
11398                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11399                 {
11400                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11401                                 continue;
11402                         switch (bihleaf->type)
11403                         {
11404                         case BIH_BRUSH:
11405                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11406                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11407                                 {
11408                                         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);
11409                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11410                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11411                                 }
11412                                 break;
11413                         case BIH_COLLISIONTRIANGLE:
11414                                 triangleindex = bihleaf->itemindex;
11415                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11416                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11417                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11418                                 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);
11419                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11420                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11421                                 break;
11422                         case BIH_RENDERTRIANGLE:
11423                                 triangleindex = bihleaf->itemindex;
11424                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11425                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11426                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11427                                 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);
11428                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11429                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11430                                 break;
11431                         }
11432                 }
11433         }
11434
11435         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11436
11437 #ifndef USE_GLES2
11438         if (r_showtris.integer && qglPolygonMode)
11439         {
11440                 if (r_showdisabledepthtest.integer)
11441                 {
11442                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11443                         GL_DepthMask(false);
11444                 }
11445                 else
11446                 {
11447                         GL_BlendFunc(GL_ONE, GL_ZERO);
11448                         GL_DepthMask(true);
11449                 }
11450                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11451                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11452                 {
11453                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11454                                 continue;
11455                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11456                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11457                         {
11458                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11459                                 if (!rsurface.texture->currentlayers->depthmask)
11460                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11461                                 else if (ent == r_refdef.scene.worldentity)
11462                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11463                                 else
11464                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11465                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11466                                 RSurf_DrawBatch();
11467                         }
11468                 }
11469                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11470                 rsurface.texture = NULL;
11471         }
11472
11473         if (r_shownormals.value != 0 && qglBegin)
11474         {
11475                 if (r_showdisabledepthtest.integer)
11476                 {
11477                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11478                         GL_DepthMask(false);
11479                 }
11480                 else
11481                 {
11482                         GL_BlendFunc(GL_ONE, GL_ZERO);
11483                         GL_DepthMask(true);
11484                 }
11485                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11486                 {
11487                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11488                                 continue;
11489                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11490                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11491                         {
11492                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11493                                 qglBegin(GL_LINES);
11494                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11495                                 {
11496                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11497                                         {
11498                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11499                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11500                                                 qglVertex3f(v[0], v[1], v[2]);
11501                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11502                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11503                                                 qglVertex3f(v[0], v[1], v[2]);
11504                                         }
11505                                 }
11506                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11507                                 {
11508                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11509                                         {
11510                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11511                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11512                                                 qglVertex3f(v[0], v[1], v[2]);
11513                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11514                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11515                                                 qglVertex3f(v[0], v[1], v[2]);
11516                                         }
11517                                 }
11518                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11519                                 {
11520                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11521                                         {
11522                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11523                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11524                                                 qglVertex3f(v[0], v[1], v[2]);
11525                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11526                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11527                                                 qglVertex3f(v[0], v[1], v[2]);
11528                                         }
11529                                 }
11530                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11531                                 {
11532                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11533                                         {
11534                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11535                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11536                                                 qglVertex3f(v[0], v[1], v[2]);
11537                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11538                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11539                                                 qglVertex3f(v[0], v[1], v[2]);
11540                                         }
11541                                 }
11542                                 qglEnd();
11543                                 CHECKGLERROR
11544                         }
11545                 }
11546                 rsurface.texture = NULL;
11547         }
11548 #endif
11549 }
11550
11551 int r_maxsurfacelist = 0;
11552 const msurface_t **r_surfacelist = NULL;
11553 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11554 {
11555         int i, j, endj, flagsmask;
11556         dp_model_t *model = r_refdef.scene.worldmodel;
11557         msurface_t *surfaces;
11558         unsigned char *update;
11559         int numsurfacelist = 0;
11560         if (model == NULL)
11561                 return;
11562
11563         if (r_maxsurfacelist < model->num_surfaces)
11564         {
11565                 r_maxsurfacelist = model->num_surfaces;
11566                 if (r_surfacelist)
11567                         Mem_Free((msurface_t**)r_surfacelist);
11568                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11569         }
11570
11571         RSurf_ActiveWorldEntity();
11572
11573         surfaces = model->data_surfaces;
11574         update = model->brushq1.lightmapupdateflags;
11575
11576         // update light styles on this submodel
11577         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11578         {
11579                 model_brush_lightstyleinfo_t *style;
11580                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11581                 {
11582                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11583                         {
11584                                 int *list = style->surfacelist;
11585                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11586                                 for (j = 0;j < style->numsurfaces;j++)
11587                                         update[list[j]] = true;
11588                         }
11589                 }
11590         }
11591
11592         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11593
11594         if (debug)
11595         {
11596                 R_DrawDebugModel();
11597                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11598                 return;
11599         }
11600
11601         rsurface.lightmaptexture = NULL;
11602         rsurface.deluxemaptexture = NULL;
11603         rsurface.uselightmaptexture = false;
11604         rsurface.texture = NULL;
11605         rsurface.rtlight = NULL;
11606         numsurfacelist = 0;
11607         // add visible surfaces to draw list
11608         for (i = 0;i < model->nummodelsurfaces;i++)
11609         {
11610                 j = model->sortedmodelsurfaces[i];
11611                 if (r_refdef.viewcache.world_surfacevisible[j])
11612                         r_surfacelist[numsurfacelist++] = surfaces + j;
11613         }
11614         // update lightmaps if needed
11615         if (model->brushq1.firstrender)
11616         {
11617                 model->brushq1.firstrender = false;
11618                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11619                         if (update[j])
11620                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11621         }
11622         else if (update)
11623         {
11624                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11625                         if (r_refdef.viewcache.world_surfacevisible[j])
11626                                 if (update[j])
11627                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11628         }
11629         // don't do anything if there were no surfaces
11630         if (!numsurfacelist)
11631         {
11632                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11633                 return;
11634         }
11635         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11636
11637         // add to stats if desired
11638         if (r_speeds.integer && !skysurfaces && !depthonly)
11639         {
11640                 r_refdef.stats.world_surfaces += numsurfacelist;
11641                 for (j = 0;j < numsurfacelist;j++)
11642                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11643         }
11644
11645         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11646 }
11647
11648 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11649 {
11650         int i, j, endj, flagsmask;
11651         dp_model_t *model = ent->model;
11652         msurface_t *surfaces;
11653         unsigned char *update;
11654         int numsurfacelist = 0;
11655         if (model == NULL)
11656                 return;
11657
11658         if (r_maxsurfacelist < model->num_surfaces)
11659         {
11660                 r_maxsurfacelist = model->num_surfaces;
11661                 if (r_surfacelist)
11662                         Mem_Free((msurface_t **)r_surfacelist);
11663                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11664         }
11665
11666         // if the model is static it doesn't matter what value we give for
11667         // wantnormals and wanttangents, so this logic uses only rules applicable
11668         // to a model, knowing that they are meaningless otherwise
11669         if (ent == r_refdef.scene.worldentity)
11670                 RSurf_ActiveWorldEntity();
11671         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11672                 RSurf_ActiveModelEntity(ent, false, false, false);
11673         else if (prepass)
11674                 RSurf_ActiveModelEntity(ent, true, true, true);
11675         else if (depthonly)
11676         {
11677                 switch (vid.renderpath)
11678                 {
11679                 case RENDERPATH_GL20:
11680                 case RENDERPATH_D3D9:
11681                 case RENDERPATH_D3D10:
11682                 case RENDERPATH_D3D11:
11683                 case RENDERPATH_SOFT:
11684                 case RENDERPATH_GLES2:
11685                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11686                         break;
11687                 case RENDERPATH_GL11:
11688                 case RENDERPATH_GL13:
11689                 case RENDERPATH_GLES1:
11690                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11691                         break;
11692                 }
11693         }
11694         else
11695         {
11696                 switch (vid.renderpath)
11697                 {
11698                 case RENDERPATH_GL20:
11699                 case RENDERPATH_D3D9:
11700                 case RENDERPATH_D3D10:
11701                 case RENDERPATH_D3D11:
11702                 case RENDERPATH_SOFT:
11703                 case RENDERPATH_GLES2:
11704                         RSurf_ActiveModelEntity(ent, true, true, false);
11705                         break;
11706                 case RENDERPATH_GL11:
11707                 case RENDERPATH_GL13:
11708                 case RENDERPATH_GLES1:
11709                         RSurf_ActiveModelEntity(ent, true, false, false);
11710                         break;
11711                 }
11712         }
11713
11714         surfaces = model->data_surfaces;
11715         update = model->brushq1.lightmapupdateflags;
11716
11717         // update light styles
11718         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11719         {
11720                 model_brush_lightstyleinfo_t *style;
11721                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11722                 {
11723                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11724                         {
11725                                 int *list = style->surfacelist;
11726                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11727                                 for (j = 0;j < style->numsurfaces;j++)
11728                                         update[list[j]] = true;
11729                         }
11730                 }
11731         }
11732
11733         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11734
11735         if (debug)
11736         {
11737                 R_DrawDebugModel();
11738                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11739                 return;
11740         }
11741
11742         rsurface.lightmaptexture = NULL;
11743         rsurface.deluxemaptexture = NULL;
11744         rsurface.uselightmaptexture = false;
11745         rsurface.texture = NULL;
11746         rsurface.rtlight = NULL;
11747         numsurfacelist = 0;
11748         // add visible surfaces to draw list
11749         for (i = 0;i < model->nummodelsurfaces;i++)
11750                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11751         // don't do anything if there were no surfaces
11752         if (!numsurfacelist)
11753         {
11754                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11755                 return;
11756         }
11757         // update lightmaps if needed
11758         if (update)
11759         {
11760                 int updated = 0;
11761                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11762                 {
11763                         if (update[j])
11764                         {
11765                                 updated++;
11766                                 R_BuildLightMap(ent, surfaces + j);
11767                         }
11768                 }
11769         }
11770         if (update)
11771                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11772                         if (update[j])
11773                                 R_BuildLightMap(ent, surfaces + j);
11774         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11775
11776         // add to stats if desired
11777         if (r_speeds.integer && !skysurfaces && !depthonly)
11778         {
11779                 r_refdef.stats.entities_surfaces += numsurfacelist;
11780                 for (j = 0;j < numsurfacelist;j++)
11781                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11782         }
11783
11784         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11785 }
11786
11787 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11788 {
11789         static texture_t texture;
11790         static msurface_t surface;
11791         const msurface_t *surfacelist = &surface;
11792
11793         // fake enough texture and surface state to render this geometry
11794
11795         texture.update_lastrenderframe = -1; // regenerate this texture
11796         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11797         texture.currentskinframe = skinframe;
11798         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11799         texture.offsetmapping = OFFSETMAPPING_OFF;
11800         texture.offsetscale = 1;
11801         texture.specularscalemod = 1;
11802         texture.specularpowermod = 1;
11803
11804         surface.texture = &texture;
11805         surface.num_triangles = numtriangles;
11806         surface.num_firsttriangle = firsttriangle;
11807         surface.num_vertices = numvertices;
11808         surface.num_firstvertex = firstvertex;
11809
11810         // now render it
11811         rsurface.texture = R_GetCurrentTexture(surface.texture);
11812         rsurface.lightmaptexture = NULL;
11813         rsurface.deluxemaptexture = NULL;
11814         rsurface.uselightmaptexture = false;
11815         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11816 }
11817
11818 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)
11819 {
11820         static msurface_t surface;
11821         const msurface_t *surfacelist = &surface;
11822
11823         // fake enough texture and surface state to render this geometry
11824         surface.texture = texture;
11825         surface.num_triangles = numtriangles;
11826         surface.num_firsttriangle = firsttriangle;
11827         surface.num_vertices = numvertices;
11828         surface.num_firstvertex = firstvertex;
11829
11830         // now render it
11831         rsurface.texture = R_GetCurrentTexture(surface.texture);
11832         rsurface.lightmaptexture = NULL;
11833         rsurface.deluxemaptexture = NULL;
11834         rsurface.uselightmaptexture = false;
11835         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11836 }