]> git.xonotic.org Git - xonotic/darkplaces.git/blob - gl_rmain.c
8c88310c5b99e2986ef371a39eebbd4b288c1070
[xonotic/darkplaces.git] / gl_rmain.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // r_main.c
21
22 #include "quakedef.h"
23 #include "cl_dyntexture.h"
24 #include "r_shadow.h"
25 #include "polygon.h"
26 #include "image.h"
27 #include "ft2.h"
28 #include "csprogs.h"
29 #include "cl_video.h"
30 #include "dpsoftrast.h"
31
32 #ifdef SUPPORTD3D
33 #include <d3d9.h>
34 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
35 #endif
36
37 mempool_t *r_main_mempool;
38 rtexturepool_t *r_main_texturepool;
39
40 static int r_textureframe = 0; ///< used only by R_GetCurrentTexture
41
42 static qboolean r_loadnormalmap;
43 static qboolean r_loadgloss;
44 qboolean r_loadfog;
45 static qboolean r_loaddds;
46 static qboolean r_savedds;
47
48 //
49 // screen size info
50 //
51 r_refdef_t r_refdef;
52
53 cvar_t r_motionblur = {CVAR_SAVE, "r_motionblur", "0", "screen motionblur - value represents intensity, somewhere around 0.5 recommended"};
54 cvar_t r_damageblur = {CVAR_SAVE, "r_damageblur", "0", "screen motionblur based on damage - value represents intensity, somewhere around 0.5 recommended"};
55 cvar_t r_motionblur_averaging = {CVAR_SAVE, "r_motionblur_averaging", "0.1", "sliding average reaction time for velocity (higher = slower adaption to change)"};
56 cvar_t r_motionblur_randomize = {CVAR_SAVE, "r_motionblur_randomize", "0.1", "randomizing coefficient to workaround ghosting"};
57 cvar_t r_motionblur_minblur = {CVAR_SAVE, "r_motionblur_minblur", "0.5", "factor of blur to apply at all times (always have this amount of blur no matter what the other factors are)"};
58 cvar_t r_motionblur_maxblur = {CVAR_SAVE, "r_motionblur_maxblur", "0.9", "maxmimum amount of blur"};
59 cvar_t r_motionblur_velocityfactor = {CVAR_SAVE, "r_motionblur_velocityfactor", "1", "factoring in of player velocity to the blur equation - the faster the player moves around the map, the more blur they get"};
60 cvar_t r_motionblur_velocityfactor_minspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_minspeed", "400", "lower value of velocity when it starts to factor into blur equation"};
61 cvar_t r_motionblur_velocityfactor_maxspeed = {CVAR_SAVE, "r_motionblur_velocityfactor_maxspeed", "800", "upper value of velocity when it reaches the peak factor into blur equation"};
62 cvar_t r_motionblur_mousefactor = {CVAR_SAVE, "r_motionblur_mousefactor", "2", "factoring in of mouse acceleration to the blur equation - the faster the player turns their mouse, the more blur they get"};
63 cvar_t r_motionblur_mousefactor_minspeed = {CVAR_SAVE, "r_motionblur_mousefactor_minspeed", "0", "lower value of mouse acceleration when it starts to factor into blur equation"};
64 cvar_t r_motionblur_mousefactor_maxspeed = {CVAR_SAVE, "r_motionblur_mousefactor_maxspeed", "50", "upper value of mouse acceleration when it reaches the peak factor into blur equation"};
65
66 // TODO do we want a r_equalize_entities cvar that works on all ents, or would that be a cheat?
67 cvar_t r_equalize_entities_fullbright = {CVAR_SAVE, "r_equalize_entities_fullbright", "0", "render fullbright entities by equalizing their lightness, not by not rendering light"};
68 cvar_t r_equalize_entities_minambient = {CVAR_SAVE, "r_equalize_entities_minambient", "0.5", "light equalizing: ensure at least this ambient/diffuse ratio"};
69 cvar_t r_equalize_entities_by = {CVAR_SAVE, "r_equalize_entities_by", "0.7", "light equalizing: exponent of dynamics compression (0 = no compression, 1 = full compression)"};
70 cvar_t r_equalize_entities_to = {CVAR_SAVE, "r_equalize_entities_to", "0.8", "light equalizing: target light level"};
71
72 cvar_t r_depthfirst = {CVAR_SAVE, "r_depthfirst", "0", "renders a depth-only version of the scene before normal rendering begins to eliminate overdraw, values: 0 = off, 1 = world depth, 2 = world and model depth"};
73 cvar_t r_useinfinitefarclip = {CVAR_SAVE, "r_useinfinitefarclip", "1", "enables use of a special kind of projection matrix that has an extremely large farclip"};
74 cvar_t r_farclip_base = {0, "r_farclip_base", "65536", "farclip (furthest visible distance) for rendering when r_useinfinitefarclip is 0"};
75 cvar_t r_farclip_world = {0, "r_farclip_world", "2", "adds map size to farclip multiplied by this value"};
76 cvar_t r_nearclip = {0, "r_nearclip", "1", "distance from camera of nearclip plane" };
77 cvar_t r_deformvertexes = {0, "r_deformvertexes", "1", "allows use of deformvertexes in shader files (can be turned off to check performance impact)"};
78 cvar_t r_transparent = {0, "r_transparent", "1", "allows use of transparent surfaces (can be turned off to check performance impact)"};
79 cvar_t r_transparent_alphatocoverage = {0, "r_transparent_alphatocoverage", "1", "enables GL_ALPHA_TO_COVERAGE antialiasing technique on alphablend and alphatest surfaces when using vid_samples 2 or higher"};
80 cvar_t r_transparent_sortsurfacesbynearest = {0, "r_transparent_sortsurfacesbynearest", "1", "sort entity and world surfaces by nearest point on bounding box instead of using the center of the bounding box, usually reduces sorting artifacts"};
81 cvar_t r_transparent_useplanardistance = {0, "r_transparent_useplanardistance", "0", "sort transparent meshes by distance from view plane rather than spherical distance to the chosen point"};
82 cvar_t r_showoverdraw = {0, "r_showoverdraw", "0", "shows overlapping geometry"};
83 cvar_t r_showbboxes = {0, "r_showbboxes", "0", "shows bounding boxes of server entities, value controls opacity scaling (1 = 10%,  10 = 100%)"};
84 cvar_t r_showsurfaces = {0, "r_showsurfaces", "0", "1 shows surfaces as different colors, or a value of 2 shows triangle draw order (for analyzing whether meshes are optimized for vertex cache)"};
85 cvar_t r_showtris = {0, "r_showtris", "0", "shows triangle outlines, value controls brightness (can be above 1)"};
86 cvar_t r_shownormals = {0, "r_shownormals", "0", "shows per-vertex surface normals and tangent vectors for bumpmapped lighting"};
87 cvar_t r_showlighting = {0, "r_showlighting", "0", "shows areas lit by lights, useful for finding out why some areas of a map render slowly (bright orange = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
88 cvar_t r_showshadowvolumes = {0, "r_showshadowvolumes", "0", "shows areas shadowed by lights, useful for finding out why some areas of a map render slowly (bright blue = lots of passes = slow), a value of 2 disables depth testing which can be interesting but not very useful"};
89 cvar_t r_showcollisionbrushes = {0, "r_showcollisionbrushes", "0", "draws collision brushes in quake3 maps (mode 1), mode 2 disables rendering of world (trippy!)"};
90 cvar_t r_showcollisionbrushes_polygonfactor = {0, "r_showcollisionbrushes_polygonfactor", "-1", "expands outward the brush polygons a little bit, used to make collision brushes appear infront of walls"};
91 cvar_t r_showcollisionbrushes_polygonoffset = {0, "r_showcollisionbrushes_polygonoffset", "0", "nudges brush polygon depth in hardware depth units, used to make collision brushes appear infront of walls"};
92 cvar_t r_showdisabledepthtest = {0, "r_showdisabledepthtest", "0", "disables depth testing on r_show* cvars, allowing you to see what hidden geometry the graphics card is processing"};
93 cvar_t r_drawportals = {0, "r_drawportals", "0", "shows portals (separating polygons) in world interior in quake1 maps"};
94 cvar_t r_drawentities = {0, "r_drawentities","1", "draw entities (doors, players, projectiles, etc)"};
95 cvar_t r_draw2d = {0, "r_draw2d","1", "draw 2D stuff (dangerous to turn off)"};
96 cvar_t r_drawworld = {0, "r_drawworld","1", "draw world (most static stuff)"};
97 cvar_t r_drawviewmodel = {0, "r_drawviewmodel","1", "draw your weapon model"};
98 cvar_t r_drawexteriormodel = {0, "r_drawexteriormodel","1", "draw your player model (e.g. in chase cam, reflections)"};
99 cvar_t r_cullentities_trace = {0, "r_cullentities_trace", "1", "probabistically cull invisible entities"};
100 cvar_t r_cullentities_trace_samples = {0, "r_cullentities_trace_samples", "2", "number of samples to test for entity culling (in addition to center sample)"};
101 cvar_t r_cullentities_trace_tempentitysamples = {0, "r_cullentities_trace_tempentitysamples", "-1", "number of samples to test for entity culling of temp entities (including all CSQC entities), -1 disables trace culling on these entities to prevent flicker (pvs still applies)"};
102 cvar_t r_cullentities_trace_enlarge = {0, "r_cullentities_trace_enlarge", "0", "box enlargement for entity culling"};
103 cvar_t r_cullentities_trace_delay = {0, "r_cullentities_trace_delay", "1", "number of seconds until the entity gets actually culled"};
104 cvar_t r_sortentities = {0, "r_sortentities", "0", "sort entities before drawing (might be faster)"};
105 cvar_t r_speeds = {0, "r_speeds","0", "displays rendering statistics and per-subsystem timings"};
106 cvar_t r_fullbright = {0, "r_fullbright","0", "makes map very bright and renders faster"};
107
108 cvar_t r_fakelight = {0, "r_fakelight","0", "render 'fake' lighting instead of real lightmaps"};
109 cvar_t r_fakelight_intensity = {0, "r_fakelight_intensity","0.75", "fakelight intensity modifier"};
110 #define FAKELIGHT_ENABLED (r_fakelight.integer >= 2 || (r_fakelight.integer && r_refdef.scene.worldmodel && !r_refdef.scene.worldmodel->lit))
111
112 cvar_t r_wateralpha = {CVAR_SAVE, "r_wateralpha","1", "opacity of water polygons"};
113 cvar_t r_dynamic = {CVAR_SAVE, "r_dynamic","1", "enables dynamic lights (rocket glow and such)"};
114 cvar_t r_fullbrights = {CVAR_SAVE, "r_fullbrights", "1", "enables glowing pixels in quake textures (changes need r_restart to take effect)"};
115 cvar_t r_shadows = {CVAR_SAVE, "r_shadows", "0", "casts fake stencil shadows from models onto the world (rtlights are unaffected by this); when set to 2, always cast the shadows in the direction set by r_shadows_throwdirection, otherwise use the model lighting."};
116 cvar_t r_shadows_darken = {CVAR_SAVE, "r_shadows_darken", "0.5", "how much shadowed areas will be darkened"};
117 cvar_t r_shadows_throwdistance = {CVAR_SAVE, "r_shadows_throwdistance", "500", "how far to cast shadows from models"};
118 cvar_t r_shadows_throwdirection = {CVAR_SAVE, "r_shadows_throwdirection", "0 0 -1", "override throwing direction for r_shadows 2"};
119 cvar_t r_shadows_drawafterrtlighting = {CVAR_SAVE, "r_shadows_drawafterrtlighting", "0", "draw fake shadows AFTER realtime lightning is drawn. May be useful for simulating fast sunlight on large outdoor maps with only one noshadow rtlight. The price is less realistic appearance of dynamic light shadows."};
120 cvar_t r_shadows_castfrombmodels = {CVAR_SAVE, "r_shadows_castfrombmodels", "0", "do cast shadows from bmodels"};
121 cvar_t r_shadows_focus = {CVAR_SAVE, "r_shadows_focus", "0 0 0", "offset the shadowed area focus"};
122 cvar_t r_shadows_shadowmapscale = {CVAR_SAVE, "r_shadows_shadowmapscale", "1", "increases shadowmap quality (multiply global shadowmap precision) for fake shadows. Needs shadowmapping ON."};
123 cvar_t r_q1bsp_skymasking = {0, "r_q1bsp_skymasking", "1", "allows sky polygons in quake1 maps to obscure other geometry"};
124 cvar_t r_polygonoffset_submodel_factor = {0, "r_polygonoffset_submodel_factor", "0", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
125 cvar_t r_polygonoffset_submodel_offset = {0, "r_polygonoffset_submodel_offset", "14", "biases depth values of world submodels such as doors, to prevent z-fighting artifacts in Quake maps"};
126 cvar_t r_polygonoffset_decals_factor = {0, "r_polygonoffset_decals_factor", "0", "biases depth values of decals to prevent z-fighting artifacts"};
127 cvar_t r_polygonoffset_decals_offset = {0, "r_polygonoffset_decals_offset", "-14", "biases depth values of decals to prevent z-fighting artifacts"};
128 cvar_t r_fog_exp2 = {0, "r_fog_exp2", "0", "uses GL_EXP2 fog (as in Nehahra) rather than realistic GL_EXP fog"};
129 cvar_t r_fog_clear = {0, "r_fog_clear", "1", "clears renderbuffer with fog color before render starts"};
130 cvar_t r_drawfog = {CVAR_SAVE, "r_drawfog", "1", "allows one to disable fog rendering"};
131 cvar_t r_transparentdepthmasking = {CVAR_SAVE, "r_transparentdepthmasking", "0", "enables depth writes on transparent meshes whose materially is normally opaque, this prevents seeing the inside of a transparent mesh"};
132 cvar_t r_transparent_sortmindist = {CVAR_SAVE, "r_transparent_sortmindist", "0", "lower distance limit for transparent sorting"};
133 cvar_t r_transparent_sortmaxdist = {CVAR_SAVE, "r_transparent_sortmaxdist", "32768", "upper distance limit for transparent sorting"};
134 cvar_t r_transparent_sortarraysize = {CVAR_SAVE, "r_transparent_sortarraysize", "4096", "number of distance-sorting layers"};
135
136 cvar_t gl_fogenable = {0, "gl_fogenable", "0", "nehahra fog enable (for Nehahra compatibility only)"};
137 cvar_t gl_fogdensity = {0, "gl_fogdensity", "0.25", "nehahra fog density (recommend values below 0.1) (for Nehahra compatibility only)"};
138 cvar_t gl_fogred = {0, "gl_fogred","0.3", "nehahra fog color red value (for Nehahra compatibility only)"};
139 cvar_t gl_foggreen = {0, "gl_foggreen","0.3", "nehahra fog color green value (for Nehahra compatibility only)"};
140 cvar_t gl_fogblue = {0, "gl_fogblue","0.3", "nehahra fog color blue value (for Nehahra compatibility only)"};
141 cvar_t gl_fogstart = {0, "gl_fogstart", "0", "nehahra fog start distance (for Nehahra compatibility only)"};
142 cvar_t gl_fogend = {0, "gl_fogend","0", "nehahra fog end distance (for Nehahra compatibility only)"};
143 cvar_t gl_skyclip = {0, "gl_skyclip", "4608", "nehahra farclip distance - the real fog end (for Nehahra compatibility only)"};
144
145 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)"};
146 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"};
147
148 cvar_t r_textureunits = {0, "r_textureunits", "32", "number of texture units to use in GL 1.1 and GL 1.3 rendering paths"};
149 static cvar_t gl_combine = {CVAR_READONLY, "gl_combine", "1", "indicates whether the OpenGL 1.3 rendering path is active"};
150 static cvar_t r_glsl = {CVAR_READONLY, "r_glsl", "1", "indicates whether the OpenGL 2.0 rendering path is active"};
151
152 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"};
153 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"};
154 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"};
155 cvar_t r_viewscale_fpsscaling = {CVAR_SAVE, "r_viewscale_fpsscaling", "0", "change resolution based on framerate"};
156 cvar_t r_viewscale_fpsscaling_min = {CVAR_SAVE, "r_viewscale_fpsscaling_min", "0.0625", "worst acceptable quality"};
157 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"};
158 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)"};
159 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)"};
160 cvar_t r_viewscale_fpsscaling_target = {CVAR_SAVE, "r_viewscale_fpsscaling_target", "70", "desired framerate"};
161
162 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)"};
163 cvar_t r_glsl_offsetmapping = {CVAR_SAVE, "r_glsl_offsetmapping", "0", "offset mapping effect (also known as parallax mapping or virtual displacement mapping)"};
164 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)"};
165 cvar_t r_glsl_offsetmapping_reliefmapping = {CVAR_SAVE, "r_glsl_offsetmapping_reliefmapping", "0", "relief mapping effect (higher quality)"};
166 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)"};
167 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)"};
168 cvar_t r_glsl_offsetmapping_scale = {CVAR_SAVE, "r_glsl_offsetmapping_scale", "0.04", "how deep the offset mapping effect is"};
169 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"};
170 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."};
171 cvar_t r_glsl_postprocess = {CVAR_SAVE, "r_glsl_postprocess", "0", "use a GLSL postprocessing shader"};
172 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)"};
173 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)"};
174 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)"};
175 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)"};
176 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)"};
177 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)"};
178 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)"};
179 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)"};
180
181 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)"};
182 cvar_t r_water_clippingplanebias = {CVAR_SAVE, "r_water_clippingplanebias", "1", "a rather technical setting which avoids black pixels around water edges"};
183 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"};
184 cvar_t r_water_refractdistort = {CVAR_SAVE, "r_water_refractdistort", "0.01", "how much water refractions shimmer"};
185 cvar_t r_water_reflectdistort = {CVAR_SAVE, "r_water_reflectdistort", "0.01", "how much water reflections shimmer"};
186 cvar_t r_water_scissormode = {0, "r_water_scissormode", "3", "scissor (1) or cull (2) or both (3) water renders"};
187 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"};
188 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"};
189 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)"};
190
191 cvar_t r_lerpsprites = {CVAR_SAVE, "r_lerpsprites", "0", "enables animation smoothing on sprites"};
192 cvar_t r_lerpmodels = {CVAR_SAVE, "r_lerpmodels", "1", "enables animation smoothing on models"};
193 cvar_t r_lerplightstyles = {CVAR_SAVE, "r_lerplightstyles", "0", "enable animation smoothing on flickering lights"};
194 cvar_t r_waterscroll = {CVAR_SAVE, "r_waterscroll", "1", "makes water scroll around, value controls how much"};
195
196 cvar_t r_bloom = {CVAR_SAVE, "r_bloom", "0", "enables bloom effect (makes bright pixels affect neighboring pixels)"};
197 cvar_t r_bloom_colorscale = {CVAR_SAVE, "r_bloom_colorscale", "1", "how bright the glow is"};
198
199 cvar_t r_bloom_brighten = {CVAR_SAVE, "r_bloom_brighten", "2", "how bright the glow is, after subtract/power"};
200 cvar_t r_bloom_blur = {CVAR_SAVE, "r_bloom_blur", "4", "how large the glow is"};
201 cvar_t r_bloom_resolution = {CVAR_SAVE, "r_bloom_resolution", "320", "what resolution to perform the bloom effect at (independent of screen resolution)"};
202 cvar_t r_bloom_colorexponent = {CVAR_SAVE, "r_bloom_colorexponent", "1", "how exaggerated the glow is"};
203 cvar_t r_bloom_colorsubtract = {CVAR_SAVE, "r_bloom_colorsubtract", "0.125", "reduces bloom colors by a certain amount"};
204
205 cvar_t r_hdr_scenebrightness = {CVAR_SAVE, "r_hdr_scenebrightness", "1", "global rendering brightness"};
206 cvar_t r_hdr_glowintensity = {CVAR_SAVE, "r_hdr_glowintensity", "1", "how bright light emitting textures should appear"};
207 cvar_t r_hdr_irisadaptation = {CVAR_SAVE, "r_hdr_irisadaptation", "0", "adjust scene brightness according to light intensity at player location"};
208 cvar_t r_hdr_irisadaptation_multiplier = {CVAR_SAVE, "r_hdr_irisadaptation_multiplier", "2", "brightness at which value will be 1.0"};
209 cvar_t r_hdr_irisadaptation_minvalue = {CVAR_SAVE, "r_hdr_irisadaptation_minvalue", "0.5", "minimum value that can result from multiplier / brightness"};
210 cvar_t r_hdr_irisadaptation_maxvalue = {CVAR_SAVE, "r_hdr_irisadaptation_maxvalue", "4", "maximum value that can result from multiplier / brightness"};
211 cvar_t r_hdr_irisadaptation_value = {0, "r_hdr_irisadaptation_value", "1", "current value as scenebrightness multiplier, changes continuously when irisadaptation is active"};
212 cvar_t r_hdr_irisadaptation_fade_up = {CVAR_SAVE, "r_hdr_irisadaptation_fade_up", "0.1", "fade rate at which value adjusts to darkness"};
213 cvar_t r_hdr_irisadaptation_fade_down = {CVAR_SAVE, "r_hdr_irisadaptation_fade_down", "0.5", "fade rate at which value adjusts to brightness"};
214 cvar_t r_hdr_irisadaptation_radius = {CVAR_SAVE, "r_hdr_irisadaptation_radius", "15", "lighting within this many units of the eye is averaged"};
215
216 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"};
217
218 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"};
219
220 cvar_t gl_lightmaps = {0, "gl_lightmaps", "0", "draws only lightmaps, no texture (for level designers)"};
221
222 cvar_t r_test = {0, "r_test", "0", "internal development use only, leave it alone (usually does nothing anyway)"};
223
224 cvar_t r_glsl_saturation = {CVAR_SAVE, "r_glsl_saturation", "1", "saturation multiplier (only working in glsl!)"};
225 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"};
226
227 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."};
228
229 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)"};
230
231 extern cvar_t v_glslgamma;
232 extern cvar_t v_glslgamma_2d;
233
234 extern qboolean v_flipped_state;
235
236 r_framebufferstate_t r_fb;
237
238 /// shadow volume bsp struct with automatically growing nodes buffer
239 svbsp_t r_svbsp;
240
241 rtexture_t *r_texture_blanknormalmap;
242 rtexture_t *r_texture_white;
243 rtexture_t *r_texture_grey128;
244 rtexture_t *r_texture_black;
245 rtexture_t *r_texture_notexture;
246 rtexture_t *r_texture_whitecube;
247 rtexture_t *r_texture_normalizationcube;
248 rtexture_t *r_texture_fogattenuation;
249 rtexture_t *r_texture_fogheighttexture;
250 rtexture_t *r_texture_gammaramps;
251 unsigned int r_texture_gammaramps_serial;
252 //rtexture_t *r_texture_fogintensity;
253 rtexture_t *r_texture_reflectcube;
254
255 // TODO: hash lookups?
256 typedef struct cubemapinfo_s
257 {
258         char basename[64];
259         rtexture_t *texture;
260 }
261 cubemapinfo_t;
262
263 int r_texture_numcubemaps;
264 cubemapinfo_t *r_texture_cubemaps[MAX_CUBEMAPS];
265
266 unsigned int r_queries[MAX_OCCLUSION_QUERIES];
267 unsigned int r_numqueries;
268 unsigned int r_maxqueries;
269
270 typedef struct r_qwskincache_s
271 {
272         char name[MAX_QPATH];
273         skinframe_t *skinframe;
274 }
275 r_qwskincache_t;
276
277 static r_qwskincache_t *r_qwskincache;
278 static int r_qwskincache_size;
279
280 /// vertex coordinates for a quad that covers the screen exactly
281 extern const float r_screenvertex3f[12];
282 extern const float r_d3dscreenvertex3f[12];
283 const float r_screenvertex3f[12] =
284 {
285         0, 0, 0,
286         1, 0, 0,
287         1, 1, 0,
288         0, 1, 0
289 };
290 const float r_d3dscreenvertex3f[12] =
291 {
292         0, 1, 0,
293         1, 1, 0,
294         1, 0, 0,
295         0, 0, 0
296 };
297
298 void R_ModulateColors(float *in, float *out, int verts, float r, float g, float b)
299 {
300         int i;
301         for (i = 0;i < verts;i++)
302         {
303                 out[0] = in[0] * r;
304                 out[1] = in[1] * g;
305                 out[2] = in[2] * b;
306                 out[3] = in[3];
307                 in += 4;
308                 out += 4;
309         }
310 }
311
312 void R_FillColors(float *out, int verts, float r, float g, float b, float a)
313 {
314         int i;
315         for (i = 0;i < verts;i++)
316         {
317                 out[0] = r;
318                 out[1] = g;
319                 out[2] = b;
320                 out[3] = a;
321                 out += 4;
322         }
323 }
324
325 // FIXME: move this to client?
326 void FOG_clear(void)
327 {
328         if (gamemode == GAME_NEHAHRA)
329         {
330                 Cvar_Set("gl_fogenable", "0");
331                 Cvar_Set("gl_fogdensity", "0.2");
332                 Cvar_Set("gl_fogred", "0.3");
333                 Cvar_Set("gl_foggreen", "0.3");
334                 Cvar_Set("gl_fogblue", "0.3");
335         }
336         r_refdef.fog_density = 0;
337         r_refdef.fog_red = 0;
338         r_refdef.fog_green = 0;
339         r_refdef.fog_blue = 0;
340         r_refdef.fog_alpha = 1;
341         r_refdef.fog_start = 0;
342         r_refdef.fog_end = 16384;
343         r_refdef.fog_height = 1<<30;
344         r_refdef.fog_fadedepth = 128;
345         memset(r_refdef.fog_height_texturename, 0, sizeof(r_refdef.fog_height_texturename));
346 }
347
348 static void R_BuildBlankTextures(void)
349 {
350         unsigned char data[4];
351         data[2] = 128; // normal X
352         data[1] = 128; // normal Y
353         data[0] = 255; // normal Z
354         data[3] = 255; // height
355         r_texture_blanknormalmap = R_LoadTexture2D(r_main_texturepool, "blankbump", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
356         data[0] = 255;
357         data[1] = 255;
358         data[2] = 255;
359         data[3] = 255;
360         r_texture_white = R_LoadTexture2D(r_main_texturepool, "blankwhite", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
361         data[0] = 128;
362         data[1] = 128;
363         data[2] = 128;
364         data[3] = 255;
365         r_texture_grey128 = R_LoadTexture2D(r_main_texturepool, "blankgrey128", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
366         data[0] = 0;
367         data[1] = 0;
368         data[2] = 0;
369         data[3] = 255;
370         r_texture_black = R_LoadTexture2D(r_main_texturepool, "blankblack", 1, 1, data, TEXTYPE_BGRA, TEXF_PERSISTENT, -1, NULL);
371 }
372
373 static void R_BuildNoTexture(void)
374 {
375         int x, y;
376         unsigned char pix[16][16][4];
377         // this makes a light grey/dark grey checkerboard texture
378         for (y = 0;y < 16;y++)
379         {
380                 for (x = 0;x < 16;x++)
381                 {
382                         if ((y < 8) ^ (x < 8))
383                         {
384                                 pix[y][x][0] = 128;
385                                 pix[y][x][1] = 128;
386                                 pix[y][x][2] = 128;
387                                 pix[y][x][3] = 255;
388                         }
389                         else
390                         {
391                                 pix[y][x][0] = 64;
392                                 pix[y][x][1] = 64;
393                                 pix[y][x][2] = 64;
394                                 pix[y][x][3] = 255;
395                         }
396                 }
397         }
398         r_texture_notexture = R_LoadTexture2D(r_main_texturepool, "notexture", 16, 16, &pix[0][0][0], TEXTYPE_BGRA, TEXF_MIPMAP | TEXF_PERSISTENT, -1, NULL);
399 }
400
401 static void R_BuildWhiteCube(void)
402 {
403         unsigned char data[6*1*1*4];
404         memset(data, 255, sizeof(data));
405         r_texture_whitecube = R_LoadTextureCubeMap(r_main_texturepool, "whitecube", 1, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
406 }
407
408 static void R_BuildNormalizationCube(void)
409 {
410         int x, y, side;
411         vec3_t v;
412         vec_t s, t, intensity;
413 #define NORMSIZE 64
414         unsigned char *data;
415         data = (unsigned char *)Mem_Alloc(tempmempool, 6*NORMSIZE*NORMSIZE*4);
416         for (side = 0;side < 6;side++)
417         {
418                 for (y = 0;y < NORMSIZE;y++)
419                 {
420                         for (x = 0;x < NORMSIZE;x++)
421                         {
422                                 s = (x + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
423                                 t = (y + 0.5f) * (2.0f / NORMSIZE) - 1.0f;
424                                 switch(side)
425                                 {
426                                 default:
427                                 case 0:
428                                         v[0] = 1;
429                                         v[1] = -t;
430                                         v[2] = -s;
431                                         break;
432                                 case 1:
433                                         v[0] = -1;
434                                         v[1] = -t;
435                                         v[2] = s;
436                                         break;
437                                 case 2:
438                                         v[0] = s;
439                                         v[1] = 1;
440                                         v[2] = t;
441                                         break;
442                                 case 3:
443                                         v[0] = s;
444                                         v[1] = -1;
445                                         v[2] = -t;
446                                         break;
447                                 case 4:
448                                         v[0] = s;
449                                         v[1] = -t;
450                                         v[2] = 1;
451                                         break;
452                                 case 5:
453                                         v[0] = -s;
454                                         v[1] = -t;
455                                         v[2] = -1;
456                                         break;
457                                 }
458                                 intensity = 127.0f / sqrt(DotProduct(v, v));
459                                 data[((side*64+y)*64+x)*4+2] = (unsigned char)(128.0f + intensity * v[0]);
460                                 data[((side*64+y)*64+x)*4+1] = (unsigned char)(128.0f + intensity * v[1]);
461                                 data[((side*64+y)*64+x)*4+0] = (unsigned char)(128.0f + intensity * v[2]);
462                                 data[((side*64+y)*64+x)*4+3] = 255;
463                         }
464                 }
465         }
466         r_texture_normalizationcube = R_LoadTextureCubeMap(r_main_texturepool, "normalcube", NORMSIZE, data, TEXTYPE_BGRA, TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
467         Mem_Free(data);
468 }
469
470 static void R_BuildFogTexture(void)
471 {
472         int x, b;
473 #define FOGWIDTH 256
474         unsigned char data1[FOGWIDTH][4];
475         //unsigned char data2[FOGWIDTH][4];
476         double d, r, alpha;
477
478         r_refdef.fogmasktable_start = r_refdef.fog_start;
479         r_refdef.fogmasktable_alpha = r_refdef.fog_alpha;
480         r_refdef.fogmasktable_range = r_refdef.fogrange;
481         r_refdef.fogmasktable_density = r_refdef.fog_density;
482
483         r = r_refdef.fogmasktable_range / FOGMASKTABLEWIDTH;
484         for (x = 0;x < FOGMASKTABLEWIDTH;x++)
485         {
486                 d = (x * r - r_refdef.fogmasktable_start);
487                 if(developer_extra.integer)
488                         Con_DPrintf("%f ", d);
489                 d = max(0, d);
490                 if (r_fog_exp2.integer)
491                         alpha = exp(-r_refdef.fogmasktable_density * r_refdef.fogmasktable_density * 0.0001 * d * d);
492                 else
493                         alpha = exp(-r_refdef.fogmasktable_density * 0.004 * d);
494                 if(developer_extra.integer)
495                         Con_DPrintf(" : %f ", alpha);
496                 alpha = 1 - (1 - alpha) * r_refdef.fogmasktable_alpha;
497                 if(developer_extra.integer)
498                         Con_DPrintf(" = %f\n", alpha);
499                 r_refdef.fogmasktable[x] = bound(0, alpha, 1);
500         }
501
502         for (x = 0;x < FOGWIDTH;x++)
503         {
504                 b = (int)(r_refdef.fogmasktable[x * (FOGMASKTABLEWIDTH - 1) / (FOGWIDTH - 1)] * 255);
505                 data1[x][0] = b;
506                 data1[x][1] = b;
507                 data1[x][2] = b;
508                 data1[x][3] = 255;
509                 //data2[x][0] = 255 - b;
510                 //data2[x][1] = 255 - b;
511                 //data2[x][2] = 255 - b;
512                 //data2[x][3] = 255;
513         }
514         if (r_texture_fogattenuation)
515         {
516                 R_UpdateTexture(r_texture_fogattenuation, &data1[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
517                 //R_UpdateTexture(r_texture_fogattenuation, &data2[0][0], 0, 0, 0, FOGWIDTH, 1, 1);
518         }
519         else
520         {
521                 r_texture_fogattenuation = R_LoadTexture2D(r_main_texturepool, "fogattenuation", FOGWIDTH, 1, &data1[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
522                 //r_texture_fogintensity = R_LoadTexture2D(r_main_texturepool, "fogintensity", FOGWIDTH, 1, &data2[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP, NULL);
523         }
524 }
525
526 static void R_BuildFogHeightTexture(void)
527 {
528         unsigned char *inpixels;
529         int size;
530         int x;
531         int y;
532         int j;
533         float c[4];
534         float f;
535         inpixels = NULL;
536         strlcpy(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename, sizeof(r_refdef.fogheighttexturename));
537         if (r_refdef.fogheighttexturename[0])
538                 inpixels = loadimagepixelsbgra(r_refdef.fogheighttexturename, true, false, false, NULL);
539         if (!inpixels)
540         {
541                 r_refdef.fog_height_tablesize = 0;
542                 if (r_texture_fogheighttexture)
543                         R_FreeTexture(r_texture_fogheighttexture);
544                 r_texture_fogheighttexture = NULL;
545                 if (r_refdef.fog_height_table2d)
546                         Mem_Free(r_refdef.fog_height_table2d);
547                 r_refdef.fog_height_table2d = NULL;
548                 if (r_refdef.fog_height_table1d)
549                         Mem_Free(r_refdef.fog_height_table1d);
550                 r_refdef.fog_height_table1d = NULL;
551                 return;
552         }
553         size = image_width;
554         r_refdef.fog_height_tablesize = size;
555         r_refdef.fog_height_table1d = (unsigned char *)Mem_Alloc(r_main_mempool, size * 4);
556         r_refdef.fog_height_table2d = (unsigned char *)Mem_Alloc(r_main_mempool, size * size * 4);
557         memcpy(r_refdef.fog_height_table1d, inpixels, size * 4);
558         Mem_Free(inpixels);
559         // LordHavoc: now the magic - what is that table2d for?  it is a cooked
560         // average fog color table accounting for every fog layer between a point
561         // and the camera.  (Note: attenuation is handled separately!)
562         for (y = 0;y < size;y++)
563         {
564                 for (x = 0;x < size;x++)
565                 {
566                         Vector4Clear(c);
567                         f = 0;
568                         if (x < y)
569                         {
570                                 for (j = x;j <= y;j++)
571                                 {
572                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
573                                         f++;
574                                 }
575                         }
576                         else
577                         {
578                                 for (j = x;j >= y;j--)
579                                 {
580                                         Vector4Add(c, r_refdef.fog_height_table1d + j*4, c);
581                                         f++;
582                                 }
583                         }
584                         f = 1.0f / f;
585                         r_refdef.fog_height_table2d[(y*size+x)*4+0] = (unsigned char)(c[0] * f);
586                         r_refdef.fog_height_table2d[(y*size+x)*4+1] = (unsigned char)(c[1] * f);
587                         r_refdef.fog_height_table2d[(y*size+x)*4+2] = (unsigned char)(c[2] * f);
588                         r_refdef.fog_height_table2d[(y*size+x)*4+3] = (unsigned char)(c[3] * f);
589                 }
590         }
591         r_texture_fogheighttexture = R_LoadTexture2D(r_main_texturepool, "fogheighttable", size, size, r_refdef.fog_height_table2d, TEXTYPE_BGRA, TEXF_ALPHA | TEXF_CLAMP, -1, NULL);
592 }
593
594 //=======================================================================================================================================================
595
596 static const char *builtinshaderstring =
597 #include "shader_glsl.h"
598 ;
599
600 const char *builtinhlslshaderstring =
601 #include "shader_hlsl.h"
602 ;
603
604 char *glslshaderstring = NULL;
605 char *hlslshaderstring = NULL;
606
607 //=======================================================================================================================================================
608
609 typedef struct shaderpermutationinfo_s
610 {
611         const char *pretext;
612         const char *name;
613 }
614 shaderpermutationinfo_t;
615
616 typedef struct shadermodeinfo_s
617 {
618         const char *vertexfilename;
619         const char *geometryfilename;
620         const char *fragmentfilename;
621         const char *pretext;
622         const char *name;
623 }
624 shadermodeinfo_t;
625
626 // NOTE: MUST MATCH ORDER OF SHADERPERMUTATION_* DEFINES!
627 shaderpermutationinfo_t shaderpermutationinfo[SHADERPERMUTATION_COUNT] =
628 {
629         {"#define USEDIFFUSE\n", " diffuse"},
630         {"#define USEVERTEXTEXTUREBLEND\n", " vertextextureblend"},
631         {"#define USEVIEWTINT\n", " viewtint"},
632         {"#define USECOLORMAPPING\n", " colormapping"},
633         {"#define USESATURATION\n", " saturation"},
634         {"#define USEFOGINSIDE\n", " foginside"},
635         {"#define USEFOGOUTSIDE\n", " fogoutside"},
636         {"#define USEFOGHEIGHTTEXTURE\n", " fogheighttexture"},
637         {"#define USEFOGALPHAHACK\n", " fogalphahack"},
638         {"#define USEGAMMARAMPS\n", " gammaramps"},
639         {"#define USECUBEFILTER\n", " cubefilter"},
640         {"#define USEGLOW\n", " glow"},
641         {"#define USEBLOOM\n", " bloom"},
642         {"#define USESPECULAR\n", " specular"},
643         {"#define USEPOSTPROCESSING\n", " postprocessing"},
644         {"#define USEREFLECTION\n", " reflection"},
645         {"#define USEOFFSETMAPPING\n", " offsetmapping"},
646         {"#define USEOFFSETMAPPING_RELIEFMAPPING\n", " reliefmapping"},
647         {"#define USESHADOWMAP2D\n", " shadowmap2d"},
648         {"#define USESHADOWMAPVSDCT\n", " shadowmapvsdct"}, // TODO make this a static parm
649         {"#define USESHADOWMAPORTHO\n", " shadowmaportho"},
650         {"#define USEDEFERREDLIGHTMAP\n", " deferredlightmap"},
651         {"#define USEALPHAKILL\n", " alphakill"},
652         {"#define USEREFLECTCUBE\n", " reflectcube"},
653         {"#define USENORMALMAPSCROLLBLEND\n", " normalmapscrollblend"},
654         {"#define USEBOUNCEGRID\n", " bouncegrid"},
655         {"#define USEBOUNCEGRIDDIRECTIONAL\n", " bouncegriddirectional"}, // TODO make this a static parm
656         {"#define USETRIPPY\n", " trippy"},
657         {"#define USEDEPTHRGB\n", " depthrgb"},
658         {"#define USEALPHAGENVERTEX\n", "alphagenvertex"}
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         SHADERSTATICPARM_SHADOWMAPPCF_1 = 8, ///< PCF 1
854         SHADERSTATICPARM_SHADOWMAPPCF_2 = 9, ///< PCF 2
855         SHADERSTATICPARM_SHADOWSAMPLER = 10, ///< sampler
856 };
857 #define SHADERSTATICPARMS_COUNT 11
858
859 static const char *shaderstaticparmstrings_list[SHADERSTATICPARMS_COUNT];
860 static int shaderstaticparms_count = 0;
861
862 static unsigned int r_compileshader_staticparms[(SHADERSTATICPARMS_COUNT + 0x1F) >> 5] = {0};
863 #define R_COMPILESHADER_STATICPARM_ENABLE(p) r_compileshader_staticparms[(p) >> 5] |= (1 << ((p) & 0x1F))
864
865 extern qboolean r_shadow_shadowmapsampler;
866 extern int r_shadow_shadowmappcf;
867 qboolean R_CompileShader_CheckStaticParms(void)
868 {
869         static int r_compileshader_staticparms_save[1];
870         memcpy(r_compileshader_staticparms_save, r_compileshader_staticparms, sizeof(r_compileshader_staticparms));
871         memset(r_compileshader_staticparms, 0, sizeof(r_compileshader_staticparms));
872
873         // detect all
874         if (r_glsl_saturation_redcompensate.integer)
875                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SATURATION_REDCOMPENSATE);
876         if (r_glsl_vertextextureblend_usebothalphas.integer)
877                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS);
878         if (r_shadow_glossexact.integer)
879                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_EXACTSPECULARMATH);
880         if (r_glsl_postprocess.integer)
881         {
882                 if (r_glsl_postprocess_uservec1_enable.integer)
883                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC1);
884                 if (r_glsl_postprocess_uservec2_enable.integer)
885                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC2);
886                 if (r_glsl_postprocess_uservec3_enable.integer)
887                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC3);
888                 if (r_glsl_postprocess_uservec4_enable.integer)
889                         R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_POSTPROCESS_USERVEC4);
890         }
891         if (r_glsl_offsetmapping_lod.integer && r_glsl_offsetmapping_lod_distance.integer > 0)
892                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_OFFSETMAPPING_USELOD);
893
894         if (r_shadow_shadowmapsampler)
895                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWSAMPLER);
896         if (r_shadow_shadowmappcf > 1)
897                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_2);
898         else if (r_shadow_shadowmappcf)
899                 R_COMPILESHADER_STATICPARM_ENABLE(SHADERSTATICPARM_SHADOWMAPPCF_1);
900
901         return memcmp(r_compileshader_staticparms, r_compileshader_staticparms_save, sizeof(r_compileshader_staticparms)) != 0;
902 }
903
904 #define R_COMPILESHADER_STATICPARM_EMIT(p, n) \
905         if(r_compileshader_staticparms[(p) >> 5] & (1 << ((p) & 0x1F))) \
906                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "#define " n "\n"; \
907         else \
908                 shaderstaticparmstrings_list[shaderstaticparms_count++] = "\n"
909 static void R_CompileShader_AddStaticParms(unsigned int mode, unsigned int permutation)
910 {
911         shaderstaticparms_count = 0;
912
913         // emit all
914         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SATURATION_REDCOMPENSATE, "SATURATION_REDCOMPENSATE");
915         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_EXACTSPECULARMATH, "USEEXACTSPECULARMATH");
916         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC1, "USERVEC1");
917         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC2, "USERVEC2");
918         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC3, "USERVEC3");
919         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_POSTPROCESS_USERVEC4, "USERVEC4");
920         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_VERTEXTEXTUREBLEND_USEBOTHALPHAS, "USEBOTHALPHAS");
921         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_OFFSETMAPPING_USELOD, "USEOFFSETMAPPING_LOD");
922         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_1, "USESHADOWMAPPCF 1");
923         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWMAPPCF_2, "USESHADOWMAPPCF 2");
924         R_COMPILESHADER_STATICPARM_EMIT(SHADERSTATICPARM_SHADOWSAMPLER, "USESHADOWSAMPLER");
925 }
926
927 /// information about each possible shader permutation
928 r_glsl_permutation_t *r_glsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
929 /// currently selected permutation
930 r_glsl_permutation_t *r_glsl_permutation;
931 /// storage for permutations linked in the hash table
932 memexpandablearray_t r_glsl_permutationarray;
933
934 static r_glsl_permutation_t *R_GLSL_FindPermutation(unsigned int mode, unsigned int permutation)
935 {
936         //unsigned int hashdepth = 0;
937         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
938         r_glsl_permutation_t *p;
939         for (p = r_glsl_permutationhash[mode][hashindex];p;p = p->hashnext)
940         {
941                 if (p->mode == mode && p->permutation == permutation)
942                 {
943                         //if (hashdepth > 10)
944                         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
945                         return p;
946                 }
947                 //hashdepth++;
948         }
949         p = (r_glsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_glsl_permutationarray);
950         p->mode = mode;
951         p->permutation = permutation;
952         p->hashnext = r_glsl_permutationhash[mode][hashindex];
953         r_glsl_permutationhash[mode][hashindex] = p;
954         //if (hashdepth > 10)
955         //      Con_Printf("R_GLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
956         return p;
957 }
958
959 static char *R_GLSL_GetText(const char *filename, qboolean printfromdisknotice)
960 {
961         char *shaderstring;
962         if (!filename || !filename[0])
963                 return NULL;
964         if (!strcmp(filename, "glsl/default.glsl"))
965         {
966                 if (!glslshaderstring)
967                 {
968                         glslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
969                         if (glslshaderstring)
970                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
971                         else
972                                 glslshaderstring = (char *)builtinshaderstring;
973                 }
974                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(glslshaderstring) + 1);
975                 memcpy(shaderstring, glslshaderstring, strlen(glslshaderstring) + 1);
976                 return shaderstring;
977         }
978         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
979         if (shaderstring)
980         {
981                 if (printfromdisknotice)
982                         Con_DPrintf("from disk %s... ", filename);
983                 return shaderstring;
984         }
985         return shaderstring;
986 }
987
988 static void R_GLSL_CompilePermutation(r_glsl_permutation_t *p, unsigned int mode, unsigned int permutation)
989 {
990         int i;
991         int sampler;
992         shadermodeinfo_t *modeinfo = glslshadermodeinfo + mode;
993         char *vertexstring, *geometrystring, *fragmentstring;
994         char permutationname[256];
995         int vertstrings_count = 0;
996         int geomstrings_count = 0;
997         int fragstrings_count = 0;
998         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
999         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1000         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1001
1002         if (p->compiled)
1003                 return;
1004         p->compiled = true;
1005         p->program = 0;
1006
1007         permutationname[0] = 0;
1008         vertexstring   = R_GLSL_GetText(modeinfo->vertexfilename, true);
1009         geometrystring = R_GLSL_GetText(modeinfo->geometryfilename, false);
1010         fragmentstring = R_GLSL_GetText(modeinfo->fragmentfilename, false);
1011
1012         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1013
1014         // if we can do #version 130, we should (this improves quality of offset/reliefmapping thanks to textureGrad)
1015         if(vid.support.gl20shaders130)
1016         {
1017                 vertstrings_list[vertstrings_count++] = "#version 130\n";
1018                 geomstrings_list[geomstrings_count++] = "#version 130\n";
1019                 fragstrings_list[fragstrings_count++] = "#version 130\n";
1020                 vertstrings_list[vertstrings_count++] = "#define GLSL130\n";
1021                 geomstrings_list[geomstrings_count++] = "#define GLSL130\n";
1022                 fragstrings_list[fragstrings_count++] = "#define GLSL130\n";
1023         }
1024
1025         // the first pretext is which type of shader to compile as
1026         // (later these will all be bound together as a program object)
1027         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1028         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1029         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1030
1031         // the second pretext is the mode (for example a light source)
1032         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1033         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1034         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1035         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1036
1037         // now add all the permutation pretexts
1038         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1039         {
1040                 if (permutation & (1<<i))
1041                 {
1042                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1043                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1044                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1045                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1046                 }
1047                 else
1048                 {
1049                         // keep line numbers correct
1050                         vertstrings_list[vertstrings_count++] = "\n";
1051                         geomstrings_list[geomstrings_count++] = "\n";
1052                         fragstrings_list[fragstrings_count++] = "\n";
1053                 }
1054         }
1055
1056         // add static parms
1057         R_CompileShader_AddStaticParms(mode, permutation);
1058         memcpy((char *)(vertstrings_list + vertstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1059         vertstrings_count += shaderstaticparms_count;
1060         memcpy((char *)(geomstrings_list + geomstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1061         geomstrings_count += shaderstaticparms_count;
1062         memcpy((char *)(fragstrings_list + fragstrings_count), shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1063         fragstrings_count += shaderstaticparms_count;
1064
1065         // now append the shader text itself
1066         vertstrings_list[vertstrings_count++] = vertexstring;
1067         geomstrings_list[geomstrings_count++] = geometrystring;
1068         fragstrings_list[fragstrings_count++] = fragmentstring;
1069
1070         // if any sources were NULL, clear the respective list
1071         if (!vertexstring)
1072                 vertstrings_count = 0;
1073         if (!geometrystring)
1074                 geomstrings_count = 0;
1075         if (!fragmentstring)
1076                 fragstrings_count = 0;
1077
1078         // compile the shader program
1079         if (vertstrings_count + geomstrings_count + fragstrings_count)
1080                 p->program = GL_Backend_CompileProgram(vertstrings_count, vertstrings_list, geomstrings_count, geomstrings_list, fragstrings_count, fragstrings_list);
1081         if (p->program)
1082         {
1083                 CHECKGLERROR
1084                 qglUseProgram(p->program);CHECKGLERROR
1085                 // look up all the uniform variable names we care about, so we don't
1086                 // have to look them up every time we set them
1087
1088                 p->loc_Texture_First              = qglGetUniformLocation(p->program, "Texture_First");
1089                 p->loc_Texture_Second             = qglGetUniformLocation(p->program, "Texture_Second");
1090                 p->loc_Texture_GammaRamps         = qglGetUniformLocation(p->program, "Texture_GammaRamps");
1091                 p->loc_Texture_Normal             = qglGetUniformLocation(p->program, "Texture_Normal");
1092                 p->loc_Texture_Color              = qglGetUniformLocation(p->program, "Texture_Color");
1093                 p->loc_Texture_Gloss              = qglGetUniformLocation(p->program, "Texture_Gloss");
1094                 p->loc_Texture_Glow               = qglGetUniformLocation(p->program, "Texture_Glow");
1095                 p->loc_Texture_SecondaryNormal    = qglGetUniformLocation(p->program, "Texture_SecondaryNormal");
1096                 p->loc_Texture_SecondaryColor     = qglGetUniformLocation(p->program, "Texture_SecondaryColor");
1097                 p->loc_Texture_SecondaryGloss     = qglGetUniformLocation(p->program, "Texture_SecondaryGloss");
1098                 p->loc_Texture_SecondaryGlow      = qglGetUniformLocation(p->program, "Texture_SecondaryGlow");
1099                 p->loc_Texture_Pants              = qglGetUniformLocation(p->program, "Texture_Pants");
1100                 p->loc_Texture_Shirt              = qglGetUniformLocation(p->program, "Texture_Shirt");
1101                 p->loc_Texture_FogHeightTexture   = qglGetUniformLocation(p->program, "Texture_FogHeightTexture");
1102                 p->loc_Texture_FogMask            = qglGetUniformLocation(p->program, "Texture_FogMask");
1103                 p->loc_Texture_Lightmap           = qglGetUniformLocation(p->program, "Texture_Lightmap");
1104                 p->loc_Texture_Deluxemap          = qglGetUniformLocation(p->program, "Texture_Deluxemap");
1105                 p->loc_Texture_Attenuation        = qglGetUniformLocation(p->program, "Texture_Attenuation");
1106                 p->loc_Texture_Cube               = qglGetUniformLocation(p->program, "Texture_Cube");
1107                 p->loc_Texture_Refraction         = qglGetUniformLocation(p->program, "Texture_Refraction");
1108                 p->loc_Texture_Reflection         = qglGetUniformLocation(p->program, "Texture_Reflection");
1109                 p->loc_Texture_ShadowMap2D        = qglGetUniformLocation(p->program, "Texture_ShadowMap2D");
1110                 p->loc_Texture_CubeProjection     = qglGetUniformLocation(p->program, "Texture_CubeProjection");
1111                 p->loc_Texture_ScreenNormalMap    = qglGetUniformLocation(p->program, "Texture_ScreenNormalMap");
1112                 p->loc_Texture_ScreenDiffuse      = qglGetUniformLocation(p->program, "Texture_ScreenDiffuse");
1113                 p->loc_Texture_ScreenSpecular     = qglGetUniformLocation(p->program, "Texture_ScreenSpecular");
1114                 p->loc_Texture_ReflectMask        = qglGetUniformLocation(p->program, "Texture_ReflectMask");
1115                 p->loc_Texture_ReflectCube        = qglGetUniformLocation(p->program, "Texture_ReflectCube");
1116                 p->loc_Texture_BounceGrid         = qglGetUniformLocation(p->program, "Texture_BounceGrid");
1117                 p->loc_Alpha                      = qglGetUniformLocation(p->program, "Alpha");
1118                 p->loc_BloomBlur_Parameters       = qglGetUniformLocation(p->program, "BloomBlur_Parameters");
1119                 p->loc_ClientTime                 = qglGetUniformLocation(p->program, "ClientTime");
1120                 p->loc_Color_Ambient              = qglGetUniformLocation(p->program, "Color_Ambient");
1121                 p->loc_Color_Diffuse              = qglGetUniformLocation(p->program, "Color_Diffuse");
1122                 p->loc_Color_Specular             = qglGetUniformLocation(p->program, "Color_Specular");
1123                 p->loc_Color_Glow                 = qglGetUniformLocation(p->program, "Color_Glow");
1124                 p->loc_Color_Pants                = qglGetUniformLocation(p->program, "Color_Pants");
1125                 p->loc_Color_Shirt                = qglGetUniformLocation(p->program, "Color_Shirt");
1126                 p->loc_DeferredColor_Ambient      = qglGetUniformLocation(p->program, "DeferredColor_Ambient");
1127                 p->loc_DeferredColor_Diffuse      = qglGetUniformLocation(p->program, "DeferredColor_Diffuse");
1128                 p->loc_DeferredColor_Specular     = qglGetUniformLocation(p->program, "DeferredColor_Specular");
1129                 p->loc_DeferredMod_Diffuse        = qglGetUniformLocation(p->program, "DeferredMod_Diffuse");
1130                 p->loc_DeferredMod_Specular       = qglGetUniformLocation(p->program, "DeferredMod_Specular");
1131                 p->loc_DistortScaleRefractReflect = qglGetUniformLocation(p->program, "DistortScaleRefractReflect");
1132                 p->loc_EyePosition                = qglGetUniformLocation(p->program, "EyePosition");
1133                 p->loc_FogColor                   = qglGetUniformLocation(p->program, "FogColor");
1134                 p->loc_FogHeightFade              = qglGetUniformLocation(p->program, "FogHeightFade");
1135                 p->loc_FogPlane                   = qglGetUniformLocation(p->program, "FogPlane");
1136                 p->loc_FogPlaneViewDist           = qglGetUniformLocation(p->program, "FogPlaneViewDist");
1137                 p->loc_FogRangeRecip              = qglGetUniformLocation(p->program, "FogRangeRecip");
1138                 p->loc_LightColor                 = qglGetUniformLocation(p->program, "LightColor");
1139                 p->loc_LightDir                   = qglGetUniformLocation(p->program, "LightDir");
1140                 p->loc_LightPosition              = qglGetUniformLocation(p->program, "LightPosition");
1141                 p->loc_OffsetMapping_ScaleSteps   = qglGetUniformLocation(p->program, "OffsetMapping_ScaleSteps");
1142                 p->loc_OffsetMapping_LodDistance  = qglGetUniformLocation(p->program, "OffsetMapping_LodDistance");
1143                 p->loc_OffsetMapping_Bias         = qglGetUniformLocation(p->program, "OffsetMapping_Bias");
1144                 p->loc_PixelSize                  = qglGetUniformLocation(p->program, "PixelSize");
1145                 p->loc_ReflectColor               = qglGetUniformLocation(p->program, "ReflectColor");
1146                 p->loc_ReflectFactor              = qglGetUniformLocation(p->program, "ReflectFactor");
1147                 p->loc_ReflectOffset              = qglGetUniformLocation(p->program, "ReflectOffset");
1148                 p->loc_RefractColor               = qglGetUniformLocation(p->program, "RefractColor");
1149                 p->loc_Saturation                 = qglGetUniformLocation(p->program, "Saturation");
1150                 p->loc_ScreenCenterRefractReflect = qglGetUniformLocation(p->program, "ScreenCenterRefractReflect");
1151                 p->loc_ScreenScaleRefractReflect  = qglGetUniformLocation(p->program, "ScreenScaleRefractReflect");
1152                 p->loc_ScreenToDepth              = qglGetUniformLocation(p->program, "ScreenToDepth");
1153                 p->loc_ShadowMap_Parameters       = qglGetUniformLocation(p->program, "ShadowMap_Parameters");
1154                 p->loc_ShadowMap_TextureScale     = qglGetUniformLocation(p->program, "ShadowMap_TextureScale");
1155                 p->loc_SpecularPower              = qglGetUniformLocation(p->program, "SpecularPower");
1156                 p->loc_UserVec1                   = qglGetUniformLocation(p->program, "UserVec1");
1157                 p->loc_UserVec2                   = qglGetUniformLocation(p->program, "UserVec2");
1158                 p->loc_UserVec3                   = qglGetUniformLocation(p->program, "UserVec3");
1159                 p->loc_UserVec4                   = qglGetUniformLocation(p->program, "UserVec4");
1160                 p->loc_ViewTintColor              = qglGetUniformLocation(p->program, "ViewTintColor");
1161                 p->loc_ViewToLight                = qglGetUniformLocation(p->program, "ViewToLight");
1162                 p->loc_ModelToLight               = qglGetUniformLocation(p->program, "ModelToLight");
1163                 p->loc_TexMatrix                  = qglGetUniformLocation(p->program, "TexMatrix");
1164                 p->loc_BackgroundTexMatrix        = qglGetUniformLocation(p->program, "BackgroundTexMatrix");
1165                 p->loc_ModelViewMatrix            = qglGetUniformLocation(p->program, "ModelViewMatrix");
1166                 p->loc_ModelViewProjectionMatrix  = qglGetUniformLocation(p->program, "ModelViewProjectionMatrix");
1167                 p->loc_PixelToScreenTexCoord      = qglGetUniformLocation(p->program, "PixelToScreenTexCoord");
1168                 p->loc_ModelToReflectCube         = qglGetUniformLocation(p->program, "ModelToReflectCube");
1169                 p->loc_ShadowMapMatrix            = qglGetUniformLocation(p->program, "ShadowMapMatrix");
1170                 p->loc_BloomColorSubtract         = qglGetUniformLocation(p->program, "BloomColorSubtract");
1171                 p->loc_NormalmapScrollBlend       = qglGetUniformLocation(p->program, "NormalmapScrollBlend");
1172                 p->loc_BounceGridMatrix           = qglGetUniformLocation(p->program, "BounceGridMatrix");
1173                 p->loc_BounceGridIntensity        = qglGetUniformLocation(p->program, "BounceGridIntensity");
1174                 // initialize the samplers to refer to the texture units we use
1175                 p->tex_Texture_First = -1;
1176                 p->tex_Texture_Second = -1;
1177                 p->tex_Texture_GammaRamps = -1;
1178                 p->tex_Texture_Normal = -1;
1179                 p->tex_Texture_Color = -1;
1180                 p->tex_Texture_Gloss = -1;
1181                 p->tex_Texture_Glow = -1;
1182                 p->tex_Texture_SecondaryNormal = -1;
1183                 p->tex_Texture_SecondaryColor = -1;
1184                 p->tex_Texture_SecondaryGloss = -1;
1185                 p->tex_Texture_SecondaryGlow = -1;
1186                 p->tex_Texture_Pants = -1;
1187                 p->tex_Texture_Shirt = -1;
1188                 p->tex_Texture_FogHeightTexture = -1;
1189                 p->tex_Texture_FogMask = -1;
1190                 p->tex_Texture_Lightmap = -1;
1191                 p->tex_Texture_Deluxemap = -1;
1192                 p->tex_Texture_Attenuation = -1;
1193                 p->tex_Texture_Cube = -1;
1194                 p->tex_Texture_Refraction = -1;
1195                 p->tex_Texture_Reflection = -1;
1196                 p->tex_Texture_ShadowMap2D = -1;
1197                 p->tex_Texture_CubeProjection = -1;
1198                 p->tex_Texture_ScreenNormalMap = -1;
1199                 p->tex_Texture_ScreenDiffuse = -1;
1200                 p->tex_Texture_ScreenSpecular = -1;
1201                 p->tex_Texture_ReflectMask = -1;
1202                 p->tex_Texture_ReflectCube = -1;
1203                 p->tex_Texture_BounceGrid = -1;
1204                 sampler = 0;
1205                 if (p->loc_Texture_First           >= 0) {p->tex_Texture_First            = sampler;qglUniform1i(p->loc_Texture_First           , sampler);sampler++;}
1206                 if (p->loc_Texture_Second          >= 0) {p->tex_Texture_Second           = sampler;qglUniform1i(p->loc_Texture_Second          , sampler);sampler++;}
1207                 if (p->loc_Texture_GammaRamps      >= 0) {p->tex_Texture_GammaRamps       = sampler;qglUniform1i(p->loc_Texture_GammaRamps      , sampler);sampler++;}
1208                 if (p->loc_Texture_Normal          >= 0) {p->tex_Texture_Normal           = sampler;qglUniform1i(p->loc_Texture_Normal          , sampler);sampler++;}
1209                 if (p->loc_Texture_Color           >= 0) {p->tex_Texture_Color            = sampler;qglUniform1i(p->loc_Texture_Color           , sampler);sampler++;}
1210                 if (p->loc_Texture_Gloss           >= 0) {p->tex_Texture_Gloss            = sampler;qglUniform1i(p->loc_Texture_Gloss           , sampler);sampler++;}
1211                 if (p->loc_Texture_Glow            >= 0) {p->tex_Texture_Glow             = sampler;qglUniform1i(p->loc_Texture_Glow            , sampler);sampler++;}
1212                 if (p->loc_Texture_SecondaryNormal >= 0) {p->tex_Texture_SecondaryNormal  = sampler;qglUniform1i(p->loc_Texture_SecondaryNormal , sampler);sampler++;}
1213                 if (p->loc_Texture_SecondaryColor  >= 0) {p->tex_Texture_SecondaryColor   = sampler;qglUniform1i(p->loc_Texture_SecondaryColor  , sampler);sampler++;}
1214                 if (p->loc_Texture_SecondaryGloss  >= 0) {p->tex_Texture_SecondaryGloss   = sampler;qglUniform1i(p->loc_Texture_SecondaryGloss  , sampler);sampler++;}
1215                 if (p->loc_Texture_SecondaryGlow   >= 0) {p->tex_Texture_SecondaryGlow    = sampler;qglUniform1i(p->loc_Texture_SecondaryGlow   , sampler);sampler++;}
1216                 if (p->loc_Texture_Pants           >= 0) {p->tex_Texture_Pants            = sampler;qglUniform1i(p->loc_Texture_Pants           , sampler);sampler++;}
1217                 if (p->loc_Texture_Shirt           >= 0) {p->tex_Texture_Shirt            = sampler;qglUniform1i(p->loc_Texture_Shirt           , sampler);sampler++;}
1218                 if (p->loc_Texture_FogHeightTexture>= 0) {p->tex_Texture_FogHeightTexture = sampler;qglUniform1i(p->loc_Texture_FogHeightTexture, sampler);sampler++;}
1219                 if (p->loc_Texture_FogMask         >= 0) {p->tex_Texture_FogMask          = sampler;qglUniform1i(p->loc_Texture_FogMask         , sampler);sampler++;}
1220                 if (p->loc_Texture_Lightmap        >= 0) {p->tex_Texture_Lightmap         = sampler;qglUniform1i(p->loc_Texture_Lightmap        , sampler);sampler++;}
1221                 if (p->loc_Texture_Deluxemap       >= 0) {p->tex_Texture_Deluxemap        = sampler;qglUniform1i(p->loc_Texture_Deluxemap       , sampler);sampler++;}
1222                 if (p->loc_Texture_Attenuation     >= 0) {p->tex_Texture_Attenuation      = sampler;qglUniform1i(p->loc_Texture_Attenuation     , sampler);sampler++;}
1223                 if (p->loc_Texture_Cube            >= 0) {p->tex_Texture_Cube             = sampler;qglUniform1i(p->loc_Texture_Cube            , sampler);sampler++;}
1224                 if (p->loc_Texture_Refraction      >= 0) {p->tex_Texture_Refraction       = sampler;qglUniform1i(p->loc_Texture_Refraction      , sampler);sampler++;}
1225                 if (p->loc_Texture_Reflection      >= 0) {p->tex_Texture_Reflection       = sampler;qglUniform1i(p->loc_Texture_Reflection      , sampler);sampler++;}
1226                 if (p->loc_Texture_ShadowMap2D     >= 0) {p->tex_Texture_ShadowMap2D      = sampler;qglUniform1i(p->loc_Texture_ShadowMap2D     , sampler);sampler++;}
1227                 if (p->loc_Texture_CubeProjection  >= 0) {p->tex_Texture_CubeProjection   = sampler;qglUniform1i(p->loc_Texture_CubeProjection  , sampler);sampler++;}
1228                 if (p->loc_Texture_ScreenNormalMap >= 0) {p->tex_Texture_ScreenNormalMap  = sampler;qglUniform1i(p->loc_Texture_ScreenNormalMap , sampler);sampler++;}
1229                 if (p->loc_Texture_ScreenDiffuse   >= 0) {p->tex_Texture_ScreenDiffuse    = sampler;qglUniform1i(p->loc_Texture_ScreenDiffuse   , sampler);sampler++;}
1230                 if (p->loc_Texture_ScreenSpecular  >= 0) {p->tex_Texture_ScreenSpecular   = sampler;qglUniform1i(p->loc_Texture_ScreenSpecular  , sampler);sampler++;}
1231                 if (p->loc_Texture_ReflectMask     >= 0) {p->tex_Texture_ReflectMask      = sampler;qglUniform1i(p->loc_Texture_ReflectMask     , sampler);sampler++;}
1232                 if (p->loc_Texture_ReflectCube     >= 0) {p->tex_Texture_ReflectCube      = sampler;qglUniform1i(p->loc_Texture_ReflectCube     , sampler);sampler++;}
1233                 if (p->loc_Texture_BounceGrid      >= 0) {p->tex_Texture_BounceGrid       = sampler;qglUniform1i(p->loc_Texture_BounceGrid      , sampler);sampler++;}
1234                 CHECKGLERROR
1235                 Con_DPrintf("^5GLSL shader %s compiled (%i textures).\n", permutationname, sampler);
1236         }
1237         else
1238                 Con_Printf("^1GLSL shader %s failed!  some features may not work properly.\n", permutationname);
1239
1240         // free the strings
1241         if (vertexstring)
1242                 Mem_Free(vertexstring);
1243         if (geometrystring)
1244                 Mem_Free(geometrystring);
1245         if (fragmentstring)
1246                 Mem_Free(fragmentstring);
1247 }
1248
1249 static void R_SetupShader_SetPermutationGLSL(unsigned int mode, unsigned int permutation)
1250 {
1251         r_glsl_permutation_t *perm = R_GLSL_FindPermutation(mode, permutation);
1252         if (r_glsl_permutation != perm)
1253         {
1254                 r_glsl_permutation = perm;
1255                 if (!r_glsl_permutation->program)
1256                 {
1257                         if (!r_glsl_permutation->compiled)
1258                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1259                         if (!r_glsl_permutation->program)
1260                         {
1261                                 // remove features until we find a valid permutation
1262                                 int i;
1263                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1264                                 {
1265                                         // reduce i more quickly whenever it would not remove any bits
1266                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1267                                         if (!(permutation & j))
1268                                                 continue;
1269                                         permutation -= j;
1270                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1271                                         if (!r_glsl_permutation->compiled)
1272                                                 R_GLSL_CompilePermutation(perm, mode, permutation);
1273                                         if (r_glsl_permutation->program)
1274                                                 break;
1275                                 }
1276                                 if (i >= SHADERPERMUTATION_COUNT)
1277                                 {
1278                                         //Con_Printf("Could not find a working OpenGL 2.0 shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1279                                         r_glsl_permutation = R_GLSL_FindPermutation(mode, permutation);
1280                                         qglUseProgram(0);CHECKGLERROR
1281                                         return; // no bit left to clear, entire mode is broken
1282                                 }
1283                         }
1284                 }
1285                 CHECKGLERROR
1286                 qglUseProgram(r_glsl_permutation->program);CHECKGLERROR
1287         }
1288         if (r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
1289         if (r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
1290         if (r_glsl_permutation->loc_ClientTime >= 0) qglUniform1f(r_glsl_permutation->loc_ClientTime, cl.time);
1291 }
1292
1293 #ifdef SUPPORTD3D
1294
1295 #ifdef SUPPORTD3D
1296 #include <d3d9.h>
1297 extern LPDIRECT3DDEVICE9 vid_d3d9dev;
1298 extern D3DCAPS9 vid_d3d9caps;
1299 #endif
1300
1301 struct r_hlsl_permutation_s;
1302 typedef struct r_hlsl_permutation_s
1303 {
1304         /// hash lookup data
1305         struct r_hlsl_permutation_s *hashnext;
1306         unsigned int mode;
1307         unsigned int permutation;
1308
1309         /// indicates if we have tried compiling this permutation already
1310         qboolean compiled;
1311         /// NULL if compilation failed
1312         IDirect3DVertexShader9 *vertexshader;
1313         IDirect3DPixelShader9 *pixelshader;
1314 }
1315 r_hlsl_permutation_t;
1316
1317 typedef enum D3DVSREGISTER_e
1318 {
1319         D3DVSREGISTER_TexMatrix = 0, // float4x4
1320         D3DVSREGISTER_BackgroundTexMatrix = 4, // float4x4
1321         D3DVSREGISTER_ModelViewProjectionMatrix = 8, // float4x4
1322         D3DVSREGISTER_ModelViewMatrix = 12, // float4x4
1323         D3DVSREGISTER_ShadowMapMatrix = 16, // float4x4
1324         D3DVSREGISTER_ModelToLight = 20, // float4x4
1325         D3DVSREGISTER_EyePosition = 24,
1326         D3DVSREGISTER_FogPlane = 25,
1327         D3DVSREGISTER_LightDir = 26,
1328         D3DVSREGISTER_LightPosition = 27,
1329 }
1330 D3DVSREGISTER_t;
1331
1332 typedef enum D3DPSREGISTER_e
1333 {
1334         D3DPSREGISTER_Alpha = 0,
1335         D3DPSREGISTER_BloomBlur_Parameters = 1,
1336         D3DPSREGISTER_ClientTime = 2,
1337         D3DPSREGISTER_Color_Ambient = 3,
1338         D3DPSREGISTER_Color_Diffuse = 4,
1339         D3DPSREGISTER_Color_Specular = 5,
1340         D3DPSREGISTER_Color_Glow = 6,
1341         D3DPSREGISTER_Color_Pants = 7,
1342         D3DPSREGISTER_Color_Shirt = 8,
1343         D3DPSREGISTER_DeferredColor_Ambient = 9,
1344         D3DPSREGISTER_DeferredColor_Diffuse = 10,
1345         D3DPSREGISTER_DeferredColor_Specular = 11,
1346         D3DPSREGISTER_DeferredMod_Diffuse = 12,
1347         D3DPSREGISTER_DeferredMod_Specular = 13,
1348         D3DPSREGISTER_DistortScaleRefractReflect = 14,
1349         D3DPSREGISTER_EyePosition = 15, // unused
1350         D3DPSREGISTER_FogColor = 16,
1351         D3DPSREGISTER_FogHeightFade = 17,
1352         D3DPSREGISTER_FogPlane = 18,
1353         D3DPSREGISTER_FogPlaneViewDist = 19,
1354         D3DPSREGISTER_FogRangeRecip = 20,
1355         D3DPSREGISTER_LightColor = 21,
1356         D3DPSREGISTER_LightDir = 22, // unused
1357         D3DPSREGISTER_LightPosition = 23,
1358         D3DPSREGISTER_OffsetMapping_ScaleSteps = 24,
1359         D3DPSREGISTER_PixelSize = 25,
1360         D3DPSREGISTER_ReflectColor = 26,
1361         D3DPSREGISTER_ReflectFactor = 27,
1362         D3DPSREGISTER_ReflectOffset = 28,
1363         D3DPSREGISTER_RefractColor = 29,
1364         D3DPSREGISTER_Saturation = 30,
1365         D3DPSREGISTER_ScreenCenterRefractReflect = 31,
1366         D3DPSREGISTER_ScreenScaleRefractReflect = 32,
1367         D3DPSREGISTER_ScreenToDepth = 33,
1368         D3DPSREGISTER_ShadowMap_Parameters = 34,
1369         D3DPSREGISTER_ShadowMap_TextureScale = 35,
1370         D3DPSREGISTER_SpecularPower = 36,
1371         D3DPSREGISTER_UserVec1 = 37,
1372         D3DPSREGISTER_UserVec2 = 38,
1373         D3DPSREGISTER_UserVec3 = 39,
1374         D3DPSREGISTER_UserVec4 = 40,
1375         D3DPSREGISTER_ViewTintColor = 41,
1376         D3DPSREGISTER_PixelToScreenTexCoord = 42,
1377         D3DPSREGISTER_BloomColorSubtract = 43,
1378         D3DPSREGISTER_ViewToLight = 44, // float4x4
1379         D3DPSREGISTER_ModelToReflectCube = 48, // float4x4
1380         D3DPSREGISTER_NormalmapScrollBlend = 52,
1381         D3DPSREGISTER_OffsetMapping_LodDistance = 53,
1382         D3DPSREGISTER_OffsetMapping_Bias = 54,
1383         // next at 54
1384 }
1385 D3DPSREGISTER_t;
1386
1387 /// information about each possible shader permutation
1388 r_hlsl_permutation_t *r_hlsl_permutationhash[SHADERMODE_COUNT][SHADERPERMUTATION_HASHSIZE];
1389 /// currently selected permutation
1390 r_hlsl_permutation_t *r_hlsl_permutation;
1391 /// storage for permutations linked in the hash table
1392 memexpandablearray_t r_hlsl_permutationarray;
1393
1394 static r_hlsl_permutation_t *R_HLSL_FindPermutation(unsigned int mode, unsigned int permutation)
1395 {
1396         //unsigned int hashdepth = 0;
1397         unsigned int hashindex = (permutation * 0x1021) & (SHADERPERMUTATION_HASHSIZE - 1);
1398         r_hlsl_permutation_t *p;
1399         for (p = r_hlsl_permutationhash[mode][hashindex];p;p = p->hashnext)
1400         {
1401                 if (p->mode == mode && p->permutation == permutation)
1402                 {
1403                         //if (hashdepth > 10)
1404                         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1405                         return p;
1406                 }
1407                 //hashdepth++;
1408         }
1409         p = (r_hlsl_permutation_t*)Mem_ExpandableArray_AllocRecord(&r_hlsl_permutationarray);
1410         p->mode = mode;
1411         p->permutation = permutation;
1412         p->hashnext = r_hlsl_permutationhash[mode][hashindex];
1413         r_hlsl_permutationhash[mode][hashindex] = p;
1414         //if (hashdepth > 10)
1415         //      Con_Printf("R_HLSL_FindPermutation: Warning: %i:%i has hashdepth %i\n", mode, permutation, hashdepth);
1416         return p;
1417 }
1418
1419 static char *R_HLSL_GetText(const char *filename, qboolean printfromdisknotice)
1420 {
1421         char *shaderstring;
1422         if (!filename || !filename[0])
1423                 return NULL;
1424         if (!strcmp(filename, "hlsl/default.hlsl"))
1425         {
1426                 if (!hlslshaderstring)
1427                 {
1428                         hlslshaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1429                         if (hlslshaderstring)
1430                                 Con_DPrintf("Loading shaders from file %s...\n", filename);
1431                         else
1432                                 hlslshaderstring = (char *)builtinhlslshaderstring;
1433                 }
1434                 shaderstring = (char *) Mem_Alloc(r_main_mempool, strlen(hlslshaderstring) + 1);
1435                 memcpy(shaderstring, hlslshaderstring, strlen(hlslshaderstring) + 1);
1436                 return shaderstring;
1437         }
1438         shaderstring = (char *)FS_LoadFile(filename, r_main_mempool, false, NULL);
1439         if (shaderstring)
1440         {
1441                 if (printfromdisknotice)
1442                         Con_DPrintf("from disk %s... ", filename);
1443                 return shaderstring;
1444         }
1445         return shaderstring;
1446 }
1447
1448 #include <d3dx9.h>
1449 //#include <d3dx9shader.h>
1450 //#include <d3dx9mesh.h>
1451
1452 static void R_HLSL_CacheShader(r_hlsl_permutation_t *p, const char *cachename, const char *vertstring, const char *fragstring)
1453 {
1454         DWORD *vsbin = NULL;
1455         DWORD *psbin = NULL;
1456         fs_offset_t vsbinsize;
1457         fs_offset_t psbinsize;
1458 //      IDirect3DVertexShader9 *vs = NULL;
1459 //      IDirect3DPixelShader9 *ps = NULL;
1460         ID3DXBuffer *vslog = NULL;
1461         ID3DXBuffer *vsbuffer = NULL;
1462         ID3DXConstantTable *vsconstanttable = NULL;
1463         ID3DXBuffer *pslog = NULL;
1464         ID3DXBuffer *psbuffer = NULL;
1465         ID3DXConstantTable *psconstanttable = NULL;
1466         int vsresult = 0;
1467         int psresult = 0;
1468         char temp[MAX_INPUTLINE];
1469         const char *vsversion = "vs_3_0", *psversion = "ps_3_0";
1470         char vabuf[1024];
1471         qboolean debugshader = gl_paranoid.integer != 0;
1472         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1473         if (p->permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) {vsversion = "vs_3_0";psversion = "ps_3_0";}
1474         if (!debugshader)
1475         {
1476                 vsbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.vsbin", cachename), r_main_mempool, true, &vsbinsize);
1477                 psbin = (DWORD *)FS_LoadFile(va(vabuf, sizeof(vabuf), "%s.psbin", cachename), r_main_mempool, true, &psbinsize);
1478         }
1479         if ((!vsbin && vertstring) || (!psbin && fragstring))
1480         {
1481                 const char* dllnames_d3dx9 [] =
1482                 {
1483                         "d3dx9_43.dll",
1484                         "d3dx9_42.dll",
1485                         "d3dx9_41.dll",
1486                         "d3dx9_40.dll",
1487                         "d3dx9_39.dll",
1488                         "d3dx9_38.dll",
1489                         "d3dx9_37.dll",
1490                         "d3dx9_36.dll",
1491                         "d3dx9_35.dll",
1492                         "d3dx9_34.dll",
1493                         "d3dx9_33.dll",
1494                         "d3dx9_32.dll",
1495                         "d3dx9_31.dll",
1496                         "d3dx9_30.dll",
1497                         "d3dx9_29.dll",
1498                         "d3dx9_28.dll",
1499                         "d3dx9_27.dll",
1500                         "d3dx9_26.dll",
1501                         "d3dx9_25.dll",
1502                         "d3dx9_24.dll",
1503                         NULL
1504                 };
1505                 dllhandle_t d3dx9_dll = NULL;
1506                 HRESULT (WINAPI *qD3DXCompileShaderFromFileA)(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1507                 HRESULT (WINAPI *qD3DXPreprocessShader)(LPCSTR pSrcData, UINT SrcDataSize, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPD3DXBUFFER* ppShaderText, LPD3DXBUFFER* ppErrorMsgs);
1508                 HRESULT (WINAPI *qD3DXCompileShader)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
1509                 dllfunction_t d3dx9_dllfuncs[] =
1510                 {
1511                         {"D3DXCompileShaderFromFileA",  (void **) &qD3DXCompileShaderFromFileA},
1512                         {"D3DXPreprocessShader",                (void **) &qD3DXPreprocessShader},
1513                         {"D3DXCompileShader",                   (void **) &qD3DXCompileShader},
1514                         {NULL, NULL}
1515                 };
1516                 if (Sys_LoadLibrary(dllnames_d3dx9, &d3dx9_dll, d3dx9_dllfuncs))
1517                 {
1518                         DWORD shaderflags = 0;
1519                         if (debugshader)
1520                                 shaderflags = D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION;
1521                         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1522                         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1523                         if (vertstring && vertstring[0])
1524                         {
1525                                 if (debugshader)
1526                                 {
1527 //                                      vsresult = qD3DXPreprocessShader(vertstring, strlen(vertstring), NULL, NULL, &vsbuffer, &vslog);
1528 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vsbuffer->GetBufferPointer(), vsbuffer->GetBufferSize());
1529                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_vs.fx", cachename), vertstring, strlen(vertstring));
1530                                         vsresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_vs.fx", fs_gamedir, cachename), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1531                                 }
1532                                 else
1533                                         vsresult = qD3DXCompileShader(vertstring, strlen(vertstring), NULL, NULL, "main", vsversion, shaderflags, &vsbuffer, &vslog, &vsconstanttable);
1534                                 if (vsbuffer)
1535                                 {
1536                                         vsbinsize = vsbuffer->GetBufferSize();
1537                                         vsbin = (DWORD *)Mem_Alloc(tempmempool, vsbinsize);
1538                                         memcpy(vsbin, vsbuffer->GetBufferPointer(), vsbinsize);
1539                                         vsbuffer->Release();
1540                                 }
1541                                 if (vslog)
1542                                 {
1543                                         strlcpy(temp, (const char *)vslog->GetBufferPointer(), min(sizeof(temp), vslog->GetBufferSize()));
1544                                         Con_DPrintf("HLSL vertex shader compile output for %s follows:\n%s\n", cachename, temp);
1545                                         vslog->Release();
1546                                 }
1547                         }
1548                         if (fragstring && fragstring[0])
1549                         {
1550                                 if (debugshader)
1551                                 {
1552 //                                      psresult = qD3DXPreprocessShader(fragstring, strlen(fragstring), NULL, NULL, &psbuffer, &pslog);
1553 //                                      FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), psbuffer->GetBufferPointer(), psbuffer->GetBufferSize());
1554                                         FS_WriteFile(va(vabuf, sizeof(vabuf), "%s_ps.fx", cachename), fragstring, strlen(fragstring));
1555                                         psresult = qD3DXCompileShaderFromFileA(va(vabuf, sizeof(vabuf), "%s/%s_ps.fx", fs_gamedir, cachename), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1556                                 }
1557                                 else
1558                                         psresult = qD3DXCompileShader(fragstring, strlen(fragstring), NULL, NULL, "main", psversion, shaderflags, &psbuffer, &pslog, &psconstanttable);
1559                                 if (psbuffer)
1560                                 {
1561                                         psbinsize = psbuffer->GetBufferSize();
1562                                         psbin = (DWORD *)Mem_Alloc(tempmempool, psbinsize);
1563                                         memcpy(psbin, psbuffer->GetBufferPointer(), psbinsize);
1564                                         psbuffer->Release();
1565                                 }
1566                                 if (pslog)
1567                                 {
1568                                         strlcpy(temp, (const char *)pslog->GetBufferPointer(), min(sizeof(temp), pslog->GetBufferSize()));
1569                                         Con_DPrintf("HLSL pixel shader compile output for %s follows:\n%s\n", cachename, temp);
1570                                         pslog->Release();
1571                                 }
1572                         }
1573                         Sys_UnloadLibrary(&d3dx9_dll);
1574                 }
1575                 else
1576                         Con_DPrintf("Unable to compile shader - D3DXCompileShader function not found\n");
1577         }
1578         if (vsbin && psbin)
1579         {
1580                 vsresult = IDirect3DDevice9_CreateVertexShader(vid_d3d9dev, vsbin, &p->vertexshader);
1581                 if (FAILED(vsresult))
1582                         Con_DPrintf("HLSL CreateVertexShader failed for %s (hresult = %8x)\n", cachename, vsresult);
1583                 psresult = IDirect3DDevice9_CreatePixelShader(vid_d3d9dev, psbin, &p->pixelshader);
1584                 if (FAILED(psresult))
1585                         Con_DPrintf("HLSL CreatePixelShader failed for %s (hresult = %8x)\n", cachename, psresult);
1586         }
1587         // free the shader data
1588         vsbin = (DWORD *)Mem_Realloc(tempmempool, vsbin, 0);
1589         psbin = (DWORD *)Mem_Realloc(tempmempool, psbin, 0);
1590 }
1591
1592 static void R_HLSL_CompilePermutation(r_hlsl_permutation_t *p, unsigned int mode, unsigned int permutation)
1593 {
1594         int i;
1595         shadermodeinfo_t *modeinfo = hlslshadermodeinfo + mode;
1596         int vertstring_length = 0;
1597         int geomstring_length = 0;
1598         int fragstring_length = 0;
1599         char *t;
1600         char *vertexstring, *geometrystring, *fragmentstring;
1601         char *vertstring, *geomstring, *fragstring;
1602         char permutationname[256];
1603         char cachename[256];
1604         int vertstrings_count = 0;
1605         int geomstrings_count = 0;
1606         int fragstrings_count = 0;
1607         const char *vertstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1608         const char *geomstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1609         const char *fragstrings_list[32+5+SHADERSTATICPARMS_COUNT+1];
1610
1611         if (p->compiled)
1612                 return;
1613         p->compiled = true;
1614         p->vertexshader = NULL;
1615         p->pixelshader = NULL;
1616
1617         permutationname[0] = 0;
1618         cachename[0] = 0;
1619         vertexstring   = R_HLSL_GetText(modeinfo->vertexfilename, true);
1620         geometrystring = R_HLSL_GetText(modeinfo->geometryfilename, false);
1621         fragmentstring = R_HLSL_GetText(modeinfo->fragmentfilename, false);
1622
1623         strlcat(permutationname, modeinfo->vertexfilename, sizeof(permutationname));
1624         strlcat(cachename, "hlsl/", sizeof(cachename));
1625
1626         // define HLSL so that the shader can tell apart the HLSL compiler and the Cg compiler
1627         vertstrings_count = 0;
1628         geomstrings_count = 0;
1629         fragstrings_count = 0;
1630         vertstrings_list[vertstrings_count++] = "#define HLSL\n";
1631         geomstrings_list[geomstrings_count++] = "#define HLSL\n";
1632         fragstrings_list[fragstrings_count++] = "#define HLSL\n";
1633
1634         // the first pretext is which type of shader to compile as
1635         // (later these will all be bound together as a program object)
1636         vertstrings_list[vertstrings_count++] = "#define VERTEX_SHADER\n";
1637         geomstrings_list[geomstrings_count++] = "#define GEOMETRY_SHADER\n";
1638         fragstrings_list[fragstrings_count++] = "#define FRAGMENT_SHADER\n";
1639
1640         // the second pretext is the mode (for example a light source)
1641         vertstrings_list[vertstrings_count++] = modeinfo->pretext;
1642         geomstrings_list[geomstrings_count++] = modeinfo->pretext;
1643         fragstrings_list[fragstrings_count++] = modeinfo->pretext;
1644         strlcat(permutationname, modeinfo->name, sizeof(permutationname));
1645         strlcat(cachename, modeinfo->name, sizeof(cachename));
1646
1647         // now add all the permutation pretexts
1648         for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1649         {
1650                 if (permutation & (1<<i))
1651                 {
1652                         vertstrings_list[vertstrings_count++] = shaderpermutationinfo[i].pretext;
1653                         geomstrings_list[geomstrings_count++] = shaderpermutationinfo[i].pretext;
1654                         fragstrings_list[fragstrings_count++] = shaderpermutationinfo[i].pretext;
1655                         strlcat(permutationname, shaderpermutationinfo[i].name, sizeof(permutationname));
1656                         strlcat(cachename, shaderpermutationinfo[i].name, sizeof(cachename));
1657                 }
1658                 else
1659                 {
1660                         // keep line numbers correct
1661                         vertstrings_list[vertstrings_count++] = "\n";
1662                         geomstrings_list[geomstrings_count++] = "\n";
1663                         fragstrings_list[fragstrings_count++] = "\n";
1664                 }
1665         }
1666
1667         // add static parms
1668         R_CompileShader_AddStaticParms(mode, permutation);
1669         memcpy(vertstrings_list + vertstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1670         vertstrings_count += shaderstaticparms_count;
1671         memcpy(geomstrings_list + geomstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1672         geomstrings_count += shaderstaticparms_count;
1673         memcpy(fragstrings_list + fragstrings_count, shaderstaticparmstrings_list, sizeof(*vertstrings_list) * shaderstaticparms_count);
1674         fragstrings_count += shaderstaticparms_count;
1675
1676         // replace spaces in the cachename with _ characters
1677         for (i = 0;cachename[i];i++)
1678                 if (cachename[i] == ' ')
1679                         cachename[i] = '_';
1680
1681         // now append the shader text itself
1682         vertstrings_list[vertstrings_count++] = vertexstring;
1683         geomstrings_list[geomstrings_count++] = geometrystring;
1684         fragstrings_list[fragstrings_count++] = fragmentstring;
1685
1686         // if any sources were NULL, clear the respective list
1687         if (!vertexstring)
1688                 vertstrings_count = 0;
1689         if (!geometrystring)
1690                 geomstrings_count = 0;
1691         if (!fragmentstring)
1692                 fragstrings_count = 0;
1693
1694         vertstring_length = 0;
1695         for (i = 0;i < vertstrings_count;i++)
1696                 vertstring_length += strlen(vertstrings_list[i]);
1697         vertstring = t = (char *)Mem_Alloc(tempmempool, vertstring_length + 1);
1698         for (i = 0;i < vertstrings_count;t += strlen(vertstrings_list[i]), i++)
1699                 memcpy(t, vertstrings_list[i], strlen(vertstrings_list[i]));
1700
1701         geomstring_length = 0;
1702         for (i = 0;i < geomstrings_count;i++)
1703                 geomstring_length += strlen(geomstrings_list[i]);
1704         geomstring = t = (char *)Mem_Alloc(tempmempool, geomstring_length + 1);
1705         for (i = 0;i < geomstrings_count;t += strlen(geomstrings_list[i]), i++)
1706                 memcpy(t, geomstrings_list[i], strlen(geomstrings_list[i]));
1707
1708         fragstring_length = 0;
1709         for (i = 0;i < fragstrings_count;i++)
1710                 fragstring_length += strlen(fragstrings_list[i]);
1711         fragstring = t = (char *)Mem_Alloc(tempmempool, fragstring_length + 1);
1712         for (i = 0;i < fragstrings_count;t += strlen(fragstrings_list[i]), i++)
1713                 memcpy(t, fragstrings_list[i], strlen(fragstrings_list[i]));
1714
1715         // try to load the cached shader, or generate one
1716         R_HLSL_CacheShader(p, cachename, vertstring, fragstring);
1717
1718         if ((p->vertexshader || !vertstring[0]) && (p->pixelshader || !fragstring[0]))
1719                 Con_DPrintf("^5HLSL shader %s compiled.\n", permutationname);
1720         else
1721                 Con_Printf("^1HLSL shader %s failed!  some features may not work properly.\n", permutationname);
1722
1723         // free the strings
1724         if (vertstring)
1725                 Mem_Free(vertstring);
1726         if (geomstring)
1727                 Mem_Free(geomstring);
1728         if (fragstring)
1729                 Mem_Free(fragstring);
1730         if (vertexstring)
1731                 Mem_Free(vertexstring);
1732         if (geometrystring)
1733                 Mem_Free(geometrystring);
1734         if (fragmentstring)
1735                 Mem_Free(fragmentstring);
1736 }
1737
1738 static inline void hlslVSSetParameter16f(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 4);}
1739 static inline void hlslVSSetParameter4fv(D3DVSREGISTER_t r, const float *a) {IDirect3DDevice9_SetVertexShaderConstantF(vid_d3d9dev, r, a, 1);}
1740 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);}
1741 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);}
1742 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);}
1743 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);}
1744
1745 static inline void hlslPSSetParameter16f(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 4);}
1746 static inline void hlslPSSetParameter4fv(D3DPSREGISTER_t r, const float *a) {IDirect3DDevice9_SetPixelShaderConstantF(vid_d3d9dev, r, a, 1);}
1747 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);}
1748 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);}
1749 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);}
1750 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);}
1751
1752 void R_SetupShader_SetPermutationHLSL(unsigned int mode, unsigned int permutation)
1753 {
1754         r_hlsl_permutation_t *perm = R_HLSL_FindPermutation(mode, permutation);
1755         if (r_hlsl_permutation != perm)
1756         {
1757                 r_hlsl_permutation = perm;
1758                 if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1759                 {
1760                         if (!r_hlsl_permutation->compiled)
1761                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1762                         if (!r_hlsl_permutation->vertexshader && !r_hlsl_permutation->pixelshader)
1763                         {
1764                                 // remove features until we find a valid permutation
1765                                 int i;
1766                                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1767                                 {
1768                                         // reduce i more quickly whenever it would not remove any bits
1769                                         int j = 1<<(SHADERPERMUTATION_COUNT-1-i);
1770                                         if (!(permutation & j))
1771                                                 continue;
1772                                         permutation -= j;
1773                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1774                                         if (!r_hlsl_permutation->compiled)
1775                                                 R_HLSL_CompilePermutation(perm, mode, permutation);
1776                                         if (r_hlsl_permutation->vertexshader || r_hlsl_permutation->pixelshader)
1777                                                 break;
1778                                 }
1779                                 if (i >= SHADERPERMUTATION_COUNT)
1780                                 {
1781                                         //Con_Printf("Could not find a working HLSL shader for permutation %s %s\n", shadermodeinfo[mode].vertexfilename, shadermodeinfo[mode].pretext);
1782                                         r_hlsl_permutation = R_HLSL_FindPermutation(mode, permutation);
1783                                         return; // no bit left to clear, entire mode is broken
1784                                 }
1785                         }
1786                 }
1787                 IDirect3DDevice9_SetVertexShader(vid_d3d9dev, r_hlsl_permutation->vertexshader);
1788                 IDirect3DDevice9_SetPixelShader(vid_d3d9dev, r_hlsl_permutation->pixelshader);
1789         }
1790         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
1791         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
1792         hlslPSSetParameter1f(D3DPSREGISTER_ClientTime, cl.time);
1793 }
1794 #endif
1795
1796 static void R_SetupShader_SetPermutationSoft(unsigned int mode, unsigned int permutation)
1797 {
1798         DPSOFTRAST_SetShader(mode, permutation, r_shadow_glossexact.integer);
1799         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
1800         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
1801         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ClientTime, cl.time);
1802 }
1803
1804 void R_GLSL_Restart_f(void)
1805 {
1806         unsigned int i, limit;
1807         if (glslshaderstring && glslshaderstring != builtinshaderstring)
1808                 Mem_Free(glslshaderstring);
1809         glslshaderstring = NULL;
1810         if (hlslshaderstring && hlslshaderstring != builtinhlslshaderstring)
1811                 Mem_Free(hlslshaderstring);
1812         hlslshaderstring = NULL;
1813         switch(vid.renderpath)
1814         {
1815         case RENDERPATH_D3D9:
1816 #ifdef SUPPORTD3D
1817                 {
1818                         r_hlsl_permutation_t *p;
1819                         r_hlsl_permutation = NULL;
1820                         limit = Mem_ExpandableArray_IndexRange(&r_hlsl_permutationarray);
1821                         for (i = 0;i < limit;i++)
1822                         {
1823                                 if ((p = (r_hlsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_hlsl_permutationarray, i)))
1824                                 {
1825                                         if (p->vertexshader)
1826                                                 IDirect3DVertexShader9_Release(p->vertexshader);
1827                                         if (p->pixelshader)
1828                                                 IDirect3DPixelShader9_Release(p->pixelshader);
1829                                         Mem_ExpandableArray_FreeRecord(&r_hlsl_permutationarray, (void*)p);
1830                                 }
1831                         }
1832                         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
1833                 }
1834 #endif
1835                 break;
1836         case RENDERPATH_D3D10:
1837                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1838                 break;
1839         case RENDERPATH_D3D11:
1840                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1841                 break;
1842         case RENDERPATH_GL20:
1843         case RENDERPATH_GLES2:
1844                 {
1845                         r_glsl_permutation_t *p;
1846                         r_glsl_permutation = NULL;
1847                         limit = Mem_ExpandableArray_IndexRange(&r_glsl_permutationarray);
1848                         for (i = 0;i < limit;i++)
1849                         {
1850                                 if ((p = (r_glsl_permutation_t*)Mem_ExpandableArray_RecordAtIndex(&r_glsl_permutationarray, i)))
1851                                 {
1852                                         GL_Backend_FreeProgram(p->program);
1853                                         Mem_ExpandableArray_FreeRecord(&r_glsl_permutationarray, (void*)p);
1854                                 }
1855                         }
1856                         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
1857                 }
1858                 break;
1859         case RENDERPATH_GL11:
1860         case RENDERPATH_GL13:
1861         case RENDERPATH_GLES1:
1862                 break;
1863         case RENDERPATH_SOFT:
1864                 break;
1865         }
1866 }
1867
1868 static void R_GLSL_DumpShader_f(void)
1869 {
1870         int i;
1871         qfile_t *file;
1872
1873         file = FS_OpenRealFile("glsl/default.glsl", "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, glslshadermodeinfo[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, builtinshaderstring);
1884                 FS_Close(file);
1885                 Con_Printf("glsl/default.glsl written\n");
1886         }
1887         else
1888                 Con_Printf("failed to write to glsl/default.glsl\n");
1889
1890         file = FS_OpenRealFile("hlsl/default.hlsl", "w", false);
1891         if (file)
1892         {
1893                 FS_Print(file, "/* The engine may define the following macros:\n");
1894                 FS_Print(file, "#define VERTEX_SHADER\n#define GEOMETRY_SHADER\n#define FRAGMENT_SHADER\n");
1895                 for (i = 0;i < SHADERMODE_COUNT;i++)
1896                         FS_Print(file, hlslshadermodeinfo[i].pretext);
1897                 for (i = 0;i < SHADERPERMUTATION_COUNT;i++)
1898                         FS_Print(file, shaderpermutationinfo[i].pretext);
1899                 FS_Print(file, "*/\n");
1900                 FS_Print(file, builtinhlslshaderstring);
1901                 FS_Close(file);
1902                 Con_Printf("hlsl/default.hlsl written\n");
1903         }
1904         else
1905                 Con_Printf("failed to write to hlsl/default.hlsl\n");
1906 }
1907
1908 void R_SetupShader_Generic(rtexture_t *first, rtexture_t *second, int texturemode, int rgbscale, qboolean usegamma, qboolean notrippy, qboolean suppresstexalpha)
1909 {
1910         unsigned int permutation = 0;
1911         if (r_trippy.integer && !notrippy)
1912                 permutation |= SHADERPERMUTATION_TRIPPY;
1913         permutation |= SHADERPERMUTATION_VIEWTINT;
1914         if (first)
1915                 permutation |= SHADERPERMUTATION_DIFFUSE;
1916         if (second)
1917                 permutation |= SHADERPERMUTATION_SPECULAR;
1918         if (texturemode == GL_MODULATE)
1919                 permutation |= SHADERPERMUTATION_COLORMAPPING;
1920         else if (texturemode == GL_ADD)
1921                 permutation |= SHADERPERMUTATION_GLOW;
1922         else if (texturemode == GL_DECAL)
1923                 permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
1924         if (usegamma && v_glslgamma.integer && v_glslgamma_2d.integer && !vid.sRGB2D && r_texture_gammaramps && !vid_gammatables_trivial)
1925                 permutation |= SHADERPERMUTATION_GAMMARAMPS;
1926         if (suppresstexalpha)
1927                 permutation |= SHADERPERMUTATION_REFLECTCUBE;
1928         if (!second)
1929                 texturemode = GL_MODULATE;
1930         if (vid.allowalphatocoverage)
1931                 GL_AlphaToCoverage(false);
1932         switch (vid.renderpath)
1933         {
1934         case RENDERPATH_D3D9:
1935 #ifdef SUPPORTD3D
1936                 R_SetupShader_SetPermutationHLSL(SHADERMODE_GENERIC, permutation);
1937                 R_Mesh_TexBind(GL20TU_FIRST , first );
1938                 R_Mesh_TexBind(GL20TU_SECOND, second);
1939                 if (permutation & SHADERPERMUTATION_GAMMARAMPS)
1940                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1941 #endif
1942                 break;
1943         case RENDERPATH_D3D10:
1944                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1945                 break;
1946         case RENDERPATH_D3D11:
1947                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1948                 break;
1949         case RENDERPATH_GL20:
1950         case RENDERPATH_GLES2:
1951                 R_SetupShader_SetPermutationGLSL(SHADERMODE_GENERIC, permutation);
1952                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First , first );
1953                 R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second, second);
1954                 if (r_glsl_permutation->tex_Texture_GammaRamps >= 0)
1955                         R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps);
1956                 break;
1957         case RENDERPATH_GL13:
1958         case RENDERPATH_GLES1:
1959                 R_Mesh_TexBind(0, first );
1960                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
1961                 R_Mesh_TexBind(1, second);
1962                 if (second)
1963                         R_Mesh_TexCombine(1, texturemode, texturemode, rgbscale, 1);
1964                 break;
1965         case RENDERPATH_GL11:
1966                 R_Mesh_TexBind(0, first );
1967                 break;
1968         case RENDERPATH_SOFT:
1969                 R_SetupShader_SetPermutationSoft(SHADERMODE_GENERIC, permutation);
1970                 R_Mesh_TexBind(GL20TU_FIRST , first );
1971                 R_Mesh_TexBind(GL20TU_SECOND, second);
1972                 break;
1973         }
1974 }
1975
1976 void R_SetupShader_Generic_NoTexture(qboolean usegamma, qboolean notrippy)
1977 {
1978         R_SetupShader_Generic(NULL, NULL, GL_MODULATE, 1, usegamma, notrippy, false);
1979 }
1980
1981 void R_SetupShader_DepthOrShadow(qboolean notrippy, qboolean depthrgb)
1982 {
1983         unsigned int permutation = 0;
1984         if (r_trippy.integer && !notrippy)
1985                 permutation |= SHADERPERMUTATION_TRIPPY;
1986         if (depthrgb)
1987                 permutation |= SHADERPERMUTATION_DEPTHRGB;
1988         if (vid.allowalphatocoverage)
1989                 GL_AlphaToCoverage(false);
1990         switch (vid.renderpath)
1991         {
1992         case RENDERPATH_D3D9:
1993 #ifdef SUPPORTD3D
1994                 R_SetupShader_SetPermutationHLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
1995 #endif
1996                 break;
1997         case RENDERPATH_D3D10:
1998                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
1999                 break;
2000         case RENDERPATH_D3D11:
2001                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2002                 break;
2003         case RENDERPATH_GL20:
2004         case RENDERPATH_GLES2:
2005                 R_SetupShader_SetPermutationGLSL(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2006                 break;
2007         case RENDERPATH_GL13:
2008         case RENDERPATH_GLES1:
2009                 R_Mesh_TexBind(0, 0);
2010                 R_Mesh_TexBind(1, 0);
2011                 break;
2012         case RENDERPATH_GL11:
2013                 R_Mesh_TexBind(0, 0);
2014                 break;
2015         case RENDERPATH_SOFT:
2016                 R_SetupShader_SetPermutationSoft(SHADERMODE_DEPTH_OR_SHADOW, permutation);
2017                 break;
2018         }
2019 }
2020
2021 void R_SetupShader_ShowDepth(qboolean notrippy)
2022 {
2023         int permutation = 0;
2024         if (r_trippy.integer && !notrippy)
2025                 permutation |= SHADERPERMUTATION_TRIPPY;
2026         if (vid.allowalphatocoverage)
2027                 GL_AlphaToCoverage(false);
2028         switch (vid.renderpath)
2029         {
2030         case RENDERPATH_D3D9:
2031 #ifdef SUPPORTHLSL
2032                 R_SetupShader_SetPermutationHLSL(SHADERMODE_SHOWDEPTH, permutation);
2033 #endif
2034                 break;
2035         case RENDERPATH_D3D10:
2036                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2037                 break;
2038         case RENDERPATH_D3D11:
2039                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2040                 break;
2041         case RENDERPATH_GL20:
2042         case RENDERPATH_GLES2:
2043                 R_SetupShader_SetPermutationGLSL(SHADERMODE_SHOWDEPTH, permutation);
2044                 break;
2045         case RENDERPATH_GL13:
2046         case RENDERPATH_GLES1:
2047                 break;
2048         case RENDERPATH_GL11:
2049                 break;
2050         case RENDERPATH_SOFT:
2051                 R_SetupShader_SetPermutationSoft(SHADERMODE_SHOWDEPTH, permutation);
2052                 break;
2053         }
2054 }
2055
2056 extern qboolean r_shadow_usingdeferredprepass;
2057 extern rtexture_t *r_shadow_attenuationgradienttexture;
2058 extern rtexture_t *r_shadow_attenuation2dtexture;
2059 extern rtexture_t *r_shadow_attenuation3dtexture;
2060 extern qboolean r_shadow_usingshadowmap2d;
2061 extern qboolean r_shadow_usingshadowmaportho;
2062 extern float r_shadow_shadowmap_texturescale[2];
2063 extern float r_shadow_shadowmap_parameters[4];
2064 extern qboolean r_shadow_shadowmapvsdct;
2065 extern rtexture_t *r_shadow_shadowmap2ddepthbuffer;
2066 extern rtexture_t *r_shadow_shadowmap2ddepthtexture;
2067 extern rtexture_t *r_shadow_shadowmapvsdcttexture;
2068 extern matrix4x4_t r_shadow_shadowmapmatrix;
2069 extern int r_shadow_shadowmaplod; // changes for each light based on distance
2070 extern int r_shadow_prepass_width;
2071 extern int r_shadow_prepass_height;
2072 extern rtexture_t *r_shadow_prepassgeometrydepthbuffer;
2073 extern rtexture_t *r_shadow_prepassgeometrynormalmaptexture;
2074 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
2075 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
2076
2077 #define BLENDFUNC_ALLOWS_COLORMOD      1
2078 #define BLENDFUNC_ALLOWS_FOG           2
2079 #define BLENDFUNC_ALLOWS_FOG_HACK0     4
2080 #define BLENDFUNC_ALLOWS_FOG_HACKALPHA 8
2081 #define BLENDFUNC_ALLOWS_ANYFOG        (BLENDFUNC_ALLOWS_FOG | BLENDFUNC_ALLOWS_FOG_HACK0 | BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2082 static int R_BlendFuncFlags(int src, int dst)
2083 {
2084         int r = 0;
2085
2086         // a blendfunc allows colormod if:
2087         // a) it can never keep the destination pixel invariant, or
2088         // b) it can keep the destination pixel invariant, and still can do so if colormodded
2089         // this is to prevent unintended side effects from colormod
2090
2091         // a blendfunc allows fog if:
2092         // blend(fog(src), fog(dst)) == fog(blend(src, dst))
2093         // this is to prevent unintended side effects from fog
2094
2095         // these checks are the output of fogeval.pl
2096
2097         r |= BLENDFUNC_ALLOWS_COLORMOD;
2098         if(src == GL_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2099         if(src == GL_DST_ALPHA && dst == GL_ONE_MINUS_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2100         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2101         if(src == GL_DST_COLOR && dst == GL_ONE_MINUS_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2102         if(src == GL_DST_COLOR && dst == GL_SRC_ALPHA) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2103         if(src == GL_DST_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2104         if(src == GL_DST_COLOR && dst == GL_ZERO) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2105         if(src == GL_ONE && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2106         if(src == GL_ONE && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG_HACKALPHA;
2107         if(src == GL_ONE && dst == GL_ZERO) r |= BLENDFUNC_ALLOWS_FOG;
2108         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_DST_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2109         if(src == GL_ONE_MINUS_DST_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2110         if(src == GL_ONE_MINUS_DST_COLOR && dst == GL_SRC_COLOR) r |= BLENDFUNC_ALLOWS_FOG;
2111         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2112         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2113         if(src == GL_ONE_MINUS_SRC_ALPHA && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2114         if(src == GL_ONE_MINUS_SRC_COLOR && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2115         if(src == GL_SRC_ALPHA && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG_HACK0;
2116         if(src == GL_SRC_ALPHA && dst == GL_ONE_MINUS_SRC_ALPHA) r |= BLENDFUNC_ALLOWS_FOG;
2117         if(src == GL_ZERO && dst == GL_ONE) r |= BLENDFUNC_ALLOWS_FOG;
2118         if(src == GL_ZERO && dst == GL_SRC_COLOR) r &= ~BLENDFUNC_ALLOWS_COLORMOD;
2119
2120         return r;
2121 }
2122
2123 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)
2124 {
2125         // select a permutation of the lighting shader appropriate to this
2126         // combination of texture, entity, light source, and fogging, only use the
2127         // minimum features necessary to avoid wasting rendering time in the
2128         // fragment shader on features that are not being used
2129         unsigned int permutation = 0;
2130         unsigned int mode = 0;
2131         int blendfuncflags;
2132         static float dummy_colormod[3] = {1, 1, 1};
2133         float *colormod = rsurface.colormod;
2134         float m16f[16];
2135         matrix4x4_t tempmatrix;
2136         r_waterstate_waterplane_t *waterplane = (r_waterstate_waterplane_t *)surfacewaterplane;
2137         if (r_trippy.integer && !notrippy)
2138                 permutation |= SHADERPERMUTATION_TRIPPY;
2139         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
2140                 permutation |= SHADERPERMUTATION_ALPHAKILL;
2141         if (rsurface.texture->r_water_waterscroll[0] && rsurface.texture->r_water_waterscroll[1])
2142                 permutation |= SHADERPERMUTATION_NORMALMAPSCROLLBLEND; // todo: make generic
2143         if (rsurfacepass == RSURFPASS_BACKGROUND)
2144         {
2145                 // distorted background
2146                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERSHADER)
2147                 {
2148                         mode = SHADERMODE_WATER;
2149                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2150                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2151                         if((r_wateralpha.value < 1) && (rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA))
2152                         {
2153                                 // this is the right thing to do for wateralpha
2154                                 GL_BlendFunc(GL_ONE, GL_ZERO);
2155                                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2156                         }
2157                         else
2158                         {
2159                                 // this is the right thing to do for entity alpha
2160                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2161                                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2162                         }
2163                 }
2164                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFRACTION)
2165                 {
2166                         mode = SHADERMODE_REFRACTION;
2167                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2168                                 permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2169                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2170                         blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2171                 }
2172                 else
2173                 {
2174                         mode = SHADERMODE_GENERIC;
2175                         permutation |= SHADERPERMUTATION_DIFFUSE;
2176                         GL_BlendFunc(GL_ONE, GL_ZERO);
2177                         blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2178                 }
2179                 if (vid.allowalphatocoverage)
2180                         GL_AlphaToCoverage(false);
2181         }
2182         else if (rsurfacepass == RSURFPASS_DEFERREDGEOMETRY)
2183         {
2184                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2185                 {
2186                         switch(rsurface.texture->offsetmapping)
2187                         {
2188                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2189                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2190                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2191                         case OFFSETMAPPING_OFF: break;
2192                         }
2193                 }
2194                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2195                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2196                 // normalmap (deferred prepass), may use alpha test on diffuse
2197                 mode = SHADERMODE_DEFERREDGEOMETRY;
2198                 GL_BlendFunc(GL_ONE, GL_ZERO);
2199                 blendfuncflags = R_BlendFuncFlags(GL_ONE, GL_ZERO);
2200                 if (vid.allowalphatocoverage)
2201                         GL_AlphaToCoverage(false);
2202         }
2203         else if (rsurfacepass == RSURFPASS_RTLIGHT)
2204         {
2205                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2206                 {
2207                         switch(rsurface.texture->offsetmapping)
2208                         {
2209                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2210                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2211                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2212                         case OFFSETMAPPING_OFF: break;
2213                         }
2214                 }
2215                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2216                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2217                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2218                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2219                 // light source
2220                 mode = SHADERMODE_LIGHTSOURCE;
2221                 if (rsurface.rtlight->currentcubemap != r_texture_whitecube)
2222                         permutation |= SHADERPERMUTATION_CUBEFILTER;
2223                 if (diffusescale > 0)
2224                         permutation |= SHADERPERMUTATION_DIFFUSE;
2225                 if (specularscale > 0)
2226                         permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2227                 if (r_refdef.fogenabled)
2228                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2229                 if (rsurface.texture->colormapping)
2230                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2231                 if (r_shadow_usingshadowmap2d)
2232                 {
2233                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2234                         if(r_shadow_shadowmapvsdct)
2235                                 permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
2236
2237                         if (r_shadow_shadowmap2ddepthbuffer)
2238                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2239                 }
2240                 if (rsurface.texture->reflectmasktexture)
2241                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2242                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
2243                 blendfuncflags = R_BlendFuncFlags(GL_SRC_ALPHA, GL_ONE);
2244                 if (vid.allowalphatocoverage)
2245                         GL_AlphaToCoverage(false);
2246         }
2247         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
2248         {
2249                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2250                 {
2251                         switch(rsurface.texture->offsetmapping)
2252                         {
2253                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2254                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2255                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2256                         case OFFSETMAPPING_OFF: break;
2257                         }
2258                 }
2259                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2260                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2261                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2262                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2263                 // unshaded geometry (fullbright or ambient model lighting)
2264                 mode = SHADERMODE_FLATCOLOR;
2265                 ambientscale = diffusescale = specularscale = 0;
2266                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2267                         permutation |= SHADERPERMUTATION_GLOW;
2268                 if (r_refdef.fogenabled)
2269                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2270                 if (rsurface.texture->colormapping)
2271                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2272                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2273                 {
2274                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2275                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2276
2277                         if (r_shadow_shadowmap2ddepthbuffer)
2278                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2279                 }
2280                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2281                         permutation |= SHADERPERMUTATION_REFLECTION;
2282                 if (rsurface.texture->reflectmasktexture)
2283                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2284                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2285                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2286                 // when using alphatocoverage, we don't need alphakill
2287                 if (vid.allowalphatocoverage)
2288                 {
2289                         if (r_transparent_alphatocoverage.integer)
2290                         {
2291                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2292                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2293                         }
2294                         else
2295                                 GL_AlphaToCoverage(false);
2296                 }
2297         }
2298         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT_DIRECTIONAL)
2299         {
2300                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2301                 {
2302                         switch(rsurface.texture->offsetmapping)
2303                         {
2304                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2305                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2306                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2307                         case OFFSETMAPPING_OFF: break;
2308                         }
2309                 }
2310                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2311                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2312                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2313                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2314                 // directional model lighting
2315                 mode = SHADERMODE_LIGHTDIRECTION;
2316                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2317                         permutation |= SHADERPERMUTATION_GLOW;
2318                 permutation |= SHADERPERMUTATION_DIFFUSE;
2319                 if (specularscale > 0)
2320                         permutation |= SHADERPERMUTATION_SPECULAR;
2321                 if (r_refdef.fogenabled)
2322                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2323                 if (rsurface.texture->colormapping)
2324                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2325                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2326                 {
2327                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2328                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2329
2330                         if (r_shadow_shadowmap2ddepthbuffer)
2331                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2332                 }
2333                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2334                         permutation |= SHADERPERMUTATION_REFLECTION;
2335                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2336                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2337                 if (rsurface.texture->reflectmasktexture)
2338                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2339                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2340                 {
2341                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2342                         if (r_shadow_bouncegriddirectional)
2343                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2344                 }
2345                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2346                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2347                 // when using alphatocoverage, we don't need alphakill
2348                 if (vid.allowalphatocoverage)
2349                 {
2350                         if (r_transparent_alphatocoverage.integer)
2351                         {
2352                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2353                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2354                         }
2355                         else
2356                                 GL_AlphaToCoverage(false);
2357                 }
2358         }
2359         else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
2360         {
2361                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2362                 {
2363                         switch(rsurface.texture->offsetmapping)
2364                         {
2365                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2366                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2367                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2368                         case OFFSETMAPPING_OFF: break;
2369                         }
2370                 }
2371                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2372                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2373                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2374                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2375                 // ambient model lighting
2376                 mode = SHADERMODE_LIGHTDIRECTION;
2377                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2378                         permutation |= SHADERPERMUTATION_GLOW;
2379                 if (r_refdef.fogenabled)
2380                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2381                 if (rsurface.texture->colormapping)
2382                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2383                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2384                 {
2385                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2386                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2387
2388                         if (r_shadow_shadowmap2ddepthbuffer)
2389                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2390                 }
2391                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2392                         permutation |= SHADERPERMUTATION_REFLECTION;
2393                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2394                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2395                 if (rsurface.texture->reflectmasktexture)
2396                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2397                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2398                 {
2399                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2400                         if (r_shadow_bouncegriddirectional)
2401                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2402                 }
2403                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2404                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2405                 // when using alphatocoverage, we don't need alphakill
2406                 if (vid.allowalphatocoverage)
2407                 {
2408                         if (r_transparent_alphatocoverage.integer)
2409                         {
2410                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2411                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2412                         }
2413                         else
2414                                 GL_AlphaToCoverage(false);
2415                 }
2416         }
2417         else
2418         {
2419                 if (r_glsl_offsetmapping.integer && ((R_TextureFlags(rsurface.texture->nmaptexture) & TEXF_ALPHA) || rsurface.texture->offsetbias != 0.0f))
2420                 {
2421                         switch(rsurface.texture->offsetmapping)
2422                         {
2423                         case OFFSETMAPPING_LINEAR: permutation |= SHADERPERMUTATION_OFFSETMAPPING;break;
2424                         case OFFSETMAPPING_RELIEF: permutation |= SHADERPERMUTATION_OFFSETMAPPING | SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2425                         case OFFSETMAPPING_DEFAULT: permutation |= SHADERPERMUTATION_OFFSETMAPPING;if (r_glsl_offsetmapping_reliefmapping.integer) permutation |= SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING;break;
2426                         case OFFSETMAPPING_OFF: break;
2427                         }
2428                 }
2429                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_VERTEXTEXTUREBLEND)
2430                         permutation |= SHADERPERMUTATION_VERTEXTEXTUREBLEND;
2431                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHAGEN_VERTEX)
2432                         permutation |= SHADERPERMUTATION_ALPHAGEN_VERTEX;
2433                 // lightmapped wall
2434                 if (rsurface.texture->glowtexture && r_hdr_glowintensity.value > 0 && !gl_lightmaps.integer)
2435                         permutation |= SHADERPERMUTATION_GLOW;
2436                 if (r_refdef.fogenabled)
2437                         permutation |= r_texture_fogheighttexture ? SHADERPERMUTATION_FOGHEIGHTTEXTURE : (r_refdef.fogplaneviewabove ? SHADERPERMUTATION_FOGOUTSIDE : SHADERPERMUTATION_FOGINSIDE);
2438                 if (rsurface.texture->colormapping)
2439                         permutation |= SHADERPERMUTATION_COLORMAPPING;
2440                 if (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW))
2441                 {
2442                         permutation |= SHADERPERMUTATION_SHADOWMAPORTHO;
2443                         permutation |= SHADERPERMUTATION_SHADOWMAP2D;
2444
2445                         if (r_shadow_shadowmap2ddepthbuffer)
2446                                 permutation |= SHADERPERMUTATION_DEPTHRGB;
2447                 }
2448                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION)
2449                         permutation |= SHADERPERMUTATION_REFLECTION;
2450                 if (r_shadow_usingdeferredprepass && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED))
2451                         permutation |= SHADERPERMUTATION_DEFERREDLIGHTMAP;
2452                 if (rsurface.texture->reflectmasktexture)
2453                         permutation |= SHADERPERMUTATION_REFLECTCUBE;
2454                 if (FAKELIGHT_ENABLED)
2455                 {
2456                         // fake lightmapping (q1bsp, q3bsp, fullbright map)
2457                         mode = SHADERMODE_FAKELIGHT;
2458                         permutation |= SHADERPERMUTATION_DIFFUSE;
2459                         if (specularscale > 0)
2460                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2461                 }
2462                 else if (r_glsl_deluxemapping.integer >= 1 && rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping)
2463                 {
2464                         // deluxemapping (light direction texture)
2465                         if (rsurface.uselightmaptexture && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brushq3.deluxemapping && r_refdef.scene.worldmodel->brushq3.deluxemapping_modelspace)
2466                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_MODELSPACE;
2467                         else
2468                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_TANGENTSPACE;
2469                         permutation |= SHADERPERMUTATION_DIFFUSE;
2470                         if (specularscale > 0)
2471                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2472                 }
2473                 else if (r_glsl_deluxemapping.integer >= 2)
2474                 {
2475                         // fake deluxemapping (uniform light direction in tangentspace)
2476                         if (rsurface.uselightmaptexture)
2477                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_LIGHTMAP;
2478                         else
2479                                 mode = SHADERMODE_LIGHTDIRECTIONMAP_FORCED_VERTEXCOLOR;
2480                         permutation |= SHADERPERMUTATION_DIFFUSE;
2481                         if (specularscale > 0)
2482                                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
2483                 }
2484                 else if (rsurface.uselightmaptexture)
2485                 {
2486                         // ordinary lightmapping (q1bsp, q3bsp)
2487                         mode = SHADERMODE_LIGHTMAP;
2488                 }
2489                 else
2490                 {
2491                         // ordinary vertex coloring (q3bsp)
2492                         mode = SHADERMODE_VERTEXCOLOR;
2493                 }
2494                 if (r_shadow_bouncegridtexture && cl.csqc_vidvars.drawworld)
2495                 {
2496                         permutation |= SHADERPERMUTATION_BOUNCEGRID;
2497                         if (r_shadow_bouncegriddirectional)
2498                                 permutation |= SHADERPERMUTATION_BOUNCEGRIDDIRECTIONAL;
2499                 }
2500                 GL_BlendFunc(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2501                 blendfuncflags = R_BlendFuncFlags(rsurface.texture->currentlayers[0].blendfunc1, rsurface.texture->currentlayers[0].blendfunc2);
2502                 // when using alphatocoverage, we don't need alphakill
2503                 if (vid.allowalphatocoverage)
2504                 {
2505                         if (r_transparent_alphatocoverage.integer)
2506                         {
2507                                 GL_AlphaToCoverage((rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST) != 0);
2508                                 permutation &= ~SHADERPERMUTATION_ALPHAKILL;
2509                         }
2510                         else
2511                                 GL_AlphaToCoverage(false);
2512                 }
2513         }
2514         if(!(blendfuncflags & BLENDFUNC_ALLOWS_COLORMOD))
2515                 colormod = dummy_colormod;
2516         if(!(blendfuncflags & BLENDFUNC_ALLOWS_ANYFOG))
2517                 permutation &= ~(SHADERPERMUTATION_FOGHEIGHTTEXTURE | SHADERPERMUTATION_FOGOUTSIDE | SHADERPERMUTATION_FOGINSIDE);
2518         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACKALPHA)
2519                 permutation |= SHADERPERMUTATION_FOGALPHAHACK;
2520         switch(vid.renderpath)
2521         {
2522         case RENDERPATH_D3D9:
2523 #ifdef SUPPORTD3D
2524                 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);
2525                 R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2526                 R_SetupShader_SetPermutationHLSL(mode, permutation);
2527                 Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);hlslPSSetParameter16f(D3DPSREGISTER_ModelToReflectCube, m16f);
2528                 if (mode == SHADERMODE_LIGHTSOURCE)
2529                 {
2530                         Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ModelToLight, m16f);
2531                         hlslVSSetParameter3f(D3DVSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2532                 }
2533                 else
2534                 {
2535                         if (mode == SHADERMODE_LIGHTDIRECTION)
2536                         {
2537                                 hlslVSSetParameter3f(D3DVSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2538                         }
2539                 }
2540                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_TexMatrix, m16f);
2541                 Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_BackgroundTexMatrix, m16f);
2542                 Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);hlslVSSetParameter16f(D3DVSREGISTER_ShadowMapMatrix, m16f);
2543                 hlslVSSetParameter3f(D3DVSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2544                 hlslVSSetParameter4f(D3DVSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2545
2546                 if (mode == SHADERMODE_LIGHTSOURCE)
2547                 {
2548                         hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2549                         hlslPSSetParameter3f(D3DPSREGISTER_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2550                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2551                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2552                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2553
2554                         // additive passes are only darkened by fog, not tinted
2555                         hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2556                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2557                 }
2558                 else
2559                 {
2560                         if (mode == SHADERMODE_FLATCOLOR)
2561                         {
2562                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2563                         }
2564                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2565                         {
2566                                 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]);
2567                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2568                                 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);
2569                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2570                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2571                                 hlslPSSetParameter3f(D3DPSREGISTER_LightColor, rsurface.modellight_diffuse[0], rsurface.modellight_diffuse[1], rsurface.modellight_diffuse[2]);
2572                                 hlslPSSetParameter3f(D3DPSREGISTER_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2573                         }
2574                         else
2575                         {
2576                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2577                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2578                                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2579                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2580                                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredMod_Specular, specularscale, specularscale, specularscale);
2581                         }
2582                         // additive passes are only darkened by fog, not tinted
2583                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2584                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, 0, 0, 0);
2585                         else
2586                                 hlslPSSetParameter3f(D3DPSREGISTER_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2587                         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);
2588                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenScaleRefractReflect, r_fb.water.screenscale[0], r_fb.water.screenscale[1], r_fb.water.screenscale[0], r_fb.water.screenscale[1]);
2589                         hlslPSSetParameter4f(D3DPSREGISTER_ScreenCenterRefractReflect, r_fb.water.screencenter[0], r_fb.water.screencenter[1], r_fb.water.screencenter[0], r_fb.water.screencenter[1]);
2590                         hlslPSSetParameter4f(D3DPSREGISTER_RefractColor, rsurface.texture->refractcolor4f[0], rsurface.texture->refractcolor4f[1], rsurface.texture->refractcolor4f[2], rsurface.texture->refractcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2591                         hlslPSSetParameter4f(D3DPSREGISTER_ReflectColor, rsurface.texture->reflectcolor4f[0], rsurface.texture->reflectcolor4f[1], rsurface.texture->reflectcolor4f[2], rsurface.texture->reflectcolor4f[3] * rsurface.texture->lightmapcolor[3]);
2592                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2593                         hlslPSSetParameter1f(D3DPSREGISTER_ReflectOffset, rsurface.texture->reflectmin);
2594                         hlslPSSetParameter1f(D3DPSREGISTER_SpecularPower, (rsurface.texture->specularpower - 1.0f) * (r_shadow_glossexact.integer ? 0.25f : 1.0f));
2595                         if (mode == SHADERMODE_WATER)
2596                                 hlslPSSetParameter2f(D3DPSREGISTER_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2597                 }
2598                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2599                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
2600                 hlslPSSetParameter3f(D3DPSREGISTER_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2601                 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));
2602                 hlslPSSetParameter3f(D3DPSREGISTER_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2603                 if (rsurface.texture->pantstexture)
2604                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2605                 else
2606                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Pants, 0, 0, 0);
2607                 if (rsurface.texture->shirttexture)
2608                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2609                 else
2610                         hlslPSSetParameter3f(D3DPSREGISTER_Color_Shirt, 0, 0, 0);
2611                 hlslPSSetParameter4f(D3DPSREGISTER_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2612                 hlslPSSetParameter1f(D3DPSREGISTER_FogPlaneViewDist, rsurface.fogplaneviewdist);
2613                 hlslPSSetParameter1f(D3DPSREGISTER_FogRangeRecip, rsurface.fograngerecip);
2614                 hlslPSSetParameter1f(D3DPSREGISTER_FogHeightFade, rsurface.fogheightfade);
2615                 hlslPSSetParameter4f(D3DPSREGISTER_OffsetMapping_ScaleSteps,
2616                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2617                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2618                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2619                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2620                         );
2621                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2622                 hlslPSSetParameter1f(D3DPSREGISTER_OffsetMapping_Bias, rsurface.texture->offsetbias);
2623                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2624                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
2625
2626                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2627                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2628                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2629                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2630                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2631                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2632                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2633                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2634                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2635                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2636                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2637                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2638                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2639                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2640                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2641                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2642                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2643                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2644                 {
2645                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2646                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2647                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2648                 }
2649                 else
2650                 {
2651                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2652                 }
2653 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2654                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2655                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2656                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2657                 {
2658                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2659                         if (rsurface.rtlight)
2660                         {
2661                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2662                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2663                         }
2664                 }
2665 #endif
2666                 break;
2667         case RENDERPATH_D3D10:
2668                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2669                 break;
2670         case RENDERPATH_D3D11:
2671                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
2672                 break;
2673         case RENDERPATH_GL20:
2674         case RENDERPATH_GLES2:
2675                 if (!vid.useinterleavedarrays)
2676                 {
2677                         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);
2678                         R_Mesh_VertexPointer(     3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
2679                         R_Mesh_ColorPointer(      4, GL_FLOAT, sizeof(float[4]), rsurface.batchlightmapcolor4f, rsurface.batchlightmapcolor4f_vertexbuffer, rsurface.batchlightmapcolor4f_bufferoffset);
2680                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
2681                         R_Mesh_TexCoordPointer(1, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchsvector3f, rsurface.batchsvector3f_vertexbuffer, rsurface.batchsvector3f_bufferoffset);
2682                         R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchtvector3f, rsurface.batchtvector3f_vertexbuffer, rsurface.batchtvector3f_bufferoffset);
2683                         R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), rsurface.batchnormal3f, rsurface.batchnormal3f_vertexbuffer, rsurface.batchnormal3f_bufferoffset);
2684                         R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
2685                 }
2686                 else
2687                 {
2688                         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);
2689                         R_Mesh_PrepareVertices_Mesh(rsurface.batchnumvertices, rsurface.batchvertexmesh, rsurface.batchvertexmeshbuffer);
2690                 }
2691                 R_SetupShader_SetPermutationGLSL(mode, permutation);
2692                 if (r_glsl_permutation->loc_ModelToReflectCube >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToReflectCube, 1, false, m16f);}
2693                 if (mode == SHADERMODE_LIGHTSOURCE)
2694                 {
2695                         if (r_glsl_permutation->loc_ModelToLight >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ModelToLight, 1, false, m16f);}
2696                         if (r_glsl_permutation->loc_LightPosition >= 0) qglUniform3f(r_glsl_permutation->loc_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2697                         if (r_glsl_permutation->loc_LightColor >= 0) qglUniform3f(r_glsl_permutation->loc_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2698                         if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2699                         if (r_glsl_permutation->loc_Color_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2700                         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);
2701         
2702                         // additive passes are only darkened by fog, not tinted
2703                         if (r_glsl_permutation->loc_FogColor >= 0)
2704                                 qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2705                         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);
2706                 }
2707                 else
2708                 {
2709                         if (mode == SHADERMODE_FLATCOLOR)
2710                         {
2711                                 if (r_glsl_permutation->loc_Color_Ambient >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2712                         }
2713                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2714                         {
2715                                 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]);
2716                                 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]);
2717                                 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);
2718                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2719                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2720                                 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]);
2721                                 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]);
2722                         }
2723                         else
2724                         {
2725                                 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]);
2726                                 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]);
2727                                 if (r_glsl_permutation->loc_Color_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2728                                 if (r_glsl_permutation->loc_DeferredMod_Diffuse >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2729                                 if (r_glsl_permutation->loc_DeferredMod_Specular >= 0) qglUniform3f(r_glsl_permutation->loc_DeferredMod_Specular, specularscale, specularscale, specularscale);
2730                         }
2731                         // additive passes are only darkened by fog, not tinted
2732                         if (r_glsl_permutation->loc_FogColor >= 0)
2733                         {
2734                                 if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2735                                         qglUniform3f(r_glsl_permutation->loc_FogColor, 0, 0, 0);
2736                                 else
2737                                         qglUniform3f(r_glsl_permutation->loc_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2738                         }
2739                         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);
2740                         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]);
2741                         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]);
2742                         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]);
2743                         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]);
2744                         if (r_glsl_permutation->loc_ReflectFactor >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2745                         if (r_glsl_permutation->loc_ReflectOffset >= 0) qglUniform1f(r_glsl_permutation->loc_ReflectOffset, rsurface.texture->reflectmin);
2746                         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);
2747                         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]);
2748                 }
2749                 if (r_glsl_permutation->loc_TexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_TexMatrix, 1, false, m16f);}
2750                 if (r_glsl_permutation->loc_BackgroundTexMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_BackgroundTexMatrix, 1, false, m16f);}
2751                 if (r_glsl_permutation->loc_ShadowMapMatrix >= 0) {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);qglUniformMatrix4fv(r_glsl_permutation->loc_ShadowMapMatrix, 1, false, m16f);}
2752                 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]);
2753                 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]);
2754
2755                 if (r_glsl_permutation->loc_Color_Glow >= 0) qglUniform3f(r_glsl_permutation->loc_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2756                 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));
2757                 if (r_glsl_permutation->loc_EyePosition >= 0) qglUniform3f(r_glsl_permutation->loc_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2758                 if (r_glsl_permutation->loc_Color_Pants >= 0)
2759                 {
2760                         if (rsurface.texture->pantstexture)
2761                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2762                         else
2763                                 qglUniform3f(r_glsl_permutation->loc_Color_Pants, 0, 0, 0);
2764                 }
2765                 if (r_glsl_permutation->loc_Color_Shirt >= 0)
2766                 {
2767                         if (rsurface.texture->shirttexture)
2768                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2769                         else
2770                                 qglUniform3f(r_glsl_permutation->loc_Color_Shirt, 0, 0, 0);
2771                 }
2772                 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]);
2773                 if (r_glsl_permutation->loc_FogPlaneViewDist >= 0) qglUniform1f(r_glsl_permutation->loc_FogPlaneViewDist, rsurface.fogplaneviewdist);
2774                 if (r_glsl_permutation->loc_FogRangeRecip >= 0) qglUniform1f(r_glsl_permutation->loc_FogRangeRecip, rsurface.fograngerecip);
2775                 if (r_glsl_permutation->loc_FogHeightFade >= 0) qglUniform1f(r_glsl_permutation->loc_FogHeightFade, rsurface.fogheightfade);
2776                 if (r_glsl_permutation->loc_OffsetMapping_ScaleSteps >= 0) qglUniform4f(r_glsl_permutation->loc_OffsetMapping_ScaleSteps,
2777                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2778                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2779                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2780                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2781                         );
2782                 if (r_glsl_permutation->loc_OffsetMapping_LodDistance >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2783                 if (r_glsl_permutation->loc_OffsetMapping_Bias >= 0) qglUniform1f(r_glsl_permutation->loc_OffsetMapping_Bias, rsurface.texture->offsetbias);
2784                 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]);
2785                 if (r_glsl_permutation->loc_PixelToScreenTexCoord >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2786                 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);}
2787                 if (r_glsl_permutation->loc_BounceGridIntensity >= 0) qglUniform1f(r_glsl_permutation->loc_BounceGridIntensity, r_shadow_bouncegridintensity*r_refdef.view.colorscale);
2788
2789                 if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First            , r_texture_white                                     );
2790                 if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second           , r_texture_white                                     );
2791                 if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps       , r_texture_gammaramps                                );
2792                 if (r_glsl_permutation->tex_Texture_Normal          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Normal           , rsurface.texture->nmaptexture                       );
2793                 if (r_glsl_permutation->tex_Texture_Color           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Color            , rsurface.texture->basetexture                       );
2794                 if (r_glsl_permutation->tex_Texture_Gloss           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Gloss            , rsurface.texture->glosstexture                      );
2795                 if (r_glsl_permutation->tex_Texture_Glow            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Glow             , rsurface.texture->glowtexture                       );
2796                 if (r_glsl_permutation->tex_Texture_SecondaryNormal >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryNormal  , rsurface.texture->backgroundnmaptexture             );
2797                 if (r_glsl_permutation->tex_Texture_SecondaryColor  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryColor   , rsurface.texture->backgroundbasetexture             );
2798                 if (r_glsl_permutation->tex_Texture_SecondaryGloss  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGloss   , rsurface.texture->backgroundglosstexture            );
2799                 if (r_glsl_permutation->tex_Texture_SecondaryGlow   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_SecondaryGlow    , rsurface.texture->backgroundglowtexture             );
2800                 if (r_glsl_permutation->tex_Texture_Pants           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Pants            , rsurface.texture->pantstexture                      );
2801                 if (r_glsl_permutation->tex_Texture_Shirt           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Shirt            , rsurface.texture->shirttexture                      );
2802                 if (r_glsl_permutation->tex_Texture_ReflectMask     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ReflectMask      , rsurface.texture->reflectmasktexture                );
2803                 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);
2804                 if (r_glsl_permutation->tex_Texture_FogHeightTexture>= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogHeightTexture , r_texture_fogheighttexture                          );
2805                 if (r_glsl_permutation->tex_Texture_FogMask         >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_FogMask          , r_texture_fogattenuation                            );
2806                 if (r_glsl_permutation->tex_Texture_Lightmap        >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Lightmap         , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2807                 if (r_glsl_permutation->tex_Texture_Deluxemap       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Deluxemap        , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2808                 if (r_glsl_permutation->tex_Texture_Attenuation     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation      , r_shadow_attenuationgradienttexture                 );
2809                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2810                 {
2811                         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);
2812                         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);
2813                         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);
2814                 }
2815                 else
2816                 {
2817                         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);
2818                 }
2819                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap   , r_shadow_prepassgeometrynormalmaptexture            );
2820                 if (r_glsl_permutation->tex_Texture_ScreenDiffuse   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenDiffuse     , r_shadow_prepasslightingdiffusetexture              );
2821                 if (r_glsl_permutation->tex_Texture_ScreenSpecular  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenSpecular    , r_shadow_prepasslightingspeculartexture             );
2822                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2823                 {
2824                         if (r_glsl_permutation->tex_Texture_ShadowMap2D     >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D, r_shadow_shadowmap2ddepthtexture                           );
2825                         if (rsurface.rtlight)
2826                         {
2827                                 if (r_glsl_permutation->tex_Texture_Cube            >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube              , rsurface.rtlight->currentcubemap                    );
2828                                 if (r_glsl_permutation->tex_Texture_CubeProjection  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection    , r_shadow_shadowmapvsdcttexture                      );
2829                         }
2830                 }
2831                 if (r_glsl_permutation->tex_Texture_BounceGrid  >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_BounceGrid, r_shadow_bouncegridtexture);
2832                 CHECKGLERROR
2833                 break;
2834         case RENDERPATH_GL11:
2835         case RENDERPATH_GL13:
2836         case RENDERPATH_GLES1:
2837                 break;
2838         case RENDERPATH_SOFT:
2839                 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);
2840                 R_Mesh_PrepareVertices_Mesh_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchsvector3f, rsurface.batchtvector3f, rsurface.batchnormal3f, rsurface.batchlightmapcolor4f, rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordlightmap2f);
2841                 R_SetupShader_SetPermutationSoft(mode, permutation);
2842                 {Matrix4x4_ToArrayFloatGL(&rsurface.matrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToReflectCubeM1, 1, false, m16f);}
2843                 if (mode == SHADERMODE_LIGHTSOURCE)
2844                 {
2845                         {Matrix4x4_ToArrayFloatGL(&rsurface.entitytolight, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelToLightM1, 1, false, m16f);}
2846                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightPosition, rsurface.entitylightorigin[0], rsurface.entitylightorigin[1], rsurface.entitylightorigin[2]);
2847                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightColor, lightcolorbase[0], lightcolorbase[1], lightcolorbase[2]);
2848                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0] * ambientscale, colormod[1] * ambientscale, colormod[2] * ambientscale);
2849                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2850                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale, r_refdef.view.colorscale * specularscale);
2851         
2852                         // additive passes are only darkened by fog, not tinted
2853                         DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2854                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2855                 }
2856                 else
2857                 {
2858                         if (mode == SHADERMODE_FLATCOLOR)
2859                         {
2860                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, colormod[0], colormod[1], colormod[2]);
2861                         }
2862                         else if (mode == SHADERMODE_LIGHTDIRECTION)
2863                         {
2864                                 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]);
2865                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, r_refdef.lightmapintensity * colormod[0], r_refdef.lightmapintensity * colormod[1], r_refdef.lightmapintensity * colormod[2]);
2866                                 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);
2867                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0], colormod[1], colormod[2]);
2868                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2869                                 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]);
2870                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_LightDir, rsurface.modellight_lightdir[0], rsurface.modellight_lightdir[1], rsurface.modellight_lightdir[2]);
2871                         }
2872                         else
2873                         {
2874                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Ambient, r_refdef.scene.ambient * colormod[0], r_refdef.scene.ambient * colormod[1], r_refdef.scene.ambient * colormod[2]);
2875                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Diffuse, rsurface.texture->lightmapcolor[0], rsurface.texture->lightmapcolor[1], rsurface.texture->lightmapcolor[2]);
2876                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Specular, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale, r_refdef.lightmapintensity * r_refdef.view.colorscale * specularscale);
2877                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Diffuse, colormod[0] * diffusescale, colormod[1] * diffusescale, colormod[2] * diffusescale);
2878                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_DeferredMod_Specular, specularscale, specularscale, specularscale);
2879                         }
2880                         // additive passes are only darkened by fog, not tinted
2881                         if(blendfuncflags & BLENDFUNC_ALLOWS_FOG_HACK0)
2882                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, 0, 0, 0);
2883                         else
2884                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_FogColor, r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2]);
2885                         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);
2886                         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]);
2887                         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]);
2888                         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]);
2889                         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]);
2890                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectFactor, rsurface.texture->reflectmax - rsurface.texture->reflectmin);
2891                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_ReflectOffset, rsurface.texture->reflectmin);
2892                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_SpecularPower, rsurface.texture->specularpower * (r_shadow_glossexact.integer ? 0.25f : 1.0f) - 1.0f);
2893                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_NormalmapScrollBlend, rsurface.texture->r_water_waterscroll[0], rsurface.texture->r_water_waterscroll[1]);
2894                 }
2895                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currenttexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_TexMatrixM1, 1, false, m16f);}
2896                 {Matrix4x4_ToArrayFloatGL(&rsurface.texture->currentbackgroundtexmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_BackgroundTexMatrixM1, 1, false, m16f);}
2897                 {Matrix4x4_ToArrayFloatGL(&r_shadow_shadowmapmatrix, m16f);DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ShadowMapMatrixM1, 1, false, m16f);}
2898                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
2899                 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]);
2900
2901                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Glow, rsurface.glowmod[0], rsurface.glowmod[1], rsurface.glowmod[2]);
2902                 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));
2903                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_EyePosition, rsurface.localvieworigin[0], rsurface.localvieworigin[1], rsurface.localvieworigin[2]);
2904                 if (DPSOFTRAST_UNIFORM_Color_Pants >= 0)
2905                 {
2906                         if (rsurface.texture->pantstexture)
2907                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, rsurface.colormap_pantscolor[0], rsurface.colormap_pantscolor[1], rsurface.colormap_pantscolor[2]);
2908                         else
2909                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Pants, 0, 0, 0);
2910                 }
2911                 if (DPSOFTRAST_UNIFORM_Color_Shirt >= 0)
2912                 {
2913                         if (rsurface.texture->shirttexture)
2914                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, rsurface.colormap_shirtcolor[0], rsurface.colormap_shirtcolor[1], rsurface.colormap_shirtcolor[2]);
2915                         else
2916                                 DPSOFTRAST_Uniform3f(DPSOFTRAST_UNIFORM_Color_Shirt, 0, 0, 0);
2917                 }
2918                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_FogPlane, rsurface.fogplane[0], rsurface.fogplane[1], rsurface.fogplane[2], rsurface.fogplane[3]);
2919                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogPlaneViewDist, rsurface.fogplaneviewdist);
2920                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogRangeRecip, rsurface.fograngerecip);
2921                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_FogHeightFade, rsurface.fogheightfade);
2922                 DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_OffsetMapping_ScaleSteps,
2923                                 r_glsl_offsetmapping_scale.value*rsurface.texture->offsetscale,
2924                                 max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2925                                 1.0 / max(1, (permutation & SHADERPERMUTATION_OFFSETMAPPING_RELIEFMAPPING) ? r_glsl_offsetmapping_reliefmapping_steps.integer : r_glsl_offsetmapping_steps.integer),
2926                                 max(1, r_glsl_offsetmapping_reliefmapping_refinesteps.integer)
2927                         );
2928                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_LodDistance, r_glsl_offsetmapping_lod_distance.integer * r_refdef.view.quality);
2929                 DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_OffsetMapping_Bias, rsurface.texture->offsetbias);
2930                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
2931                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
2932
2933                 R_Mesh_TexBind(GL20TU_NORMAL            , rsurface.texture->nmaptexture                       );
2934                 R_Mesh_TexBind(GL20TU_COLOR             , rsurface.texture->basetexture                       );
2935                 R_Mesh_TexBind(GL20TU_GLOSS             , rsurface.texture->glosstexture                      );
2936                 R_Mesh_TexBind(GL20TU_GLOW              , rsurface.texture->glowtexture                       );
2937                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_NORMAL  , rsurface.texture->backgroundnmaptexture             );
2938                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_COLOR   , rsurface.texture->backgroundbasetexture             );
2939                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOSS   , rsurface.texture->backgroundglosstexture            );
2940                 if (permutation & SHADERPERMUTATION_VERTEXTEXTUREBLEND) R_Mesh_TexBind(GL20TU_SECONDARY_GLOW    , rsurface.texture->backgroundglowtexture             );
2941                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_PANTS             , rsurface.texture->pantstexture                      );
2942                 if (permutation & SHADERPERMUTATION_COLORMAPPING) R_Mesh_TexBind(GL20TU_SHIRT             , rsurface.texture->shirttexture                      );
2943                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTMASK       , rsurface.texture->reflectmasktexture                );
2944                 if (permutation & SHADERPERMUTATION_REFLECTCUBE) R_Mesh_TexBind(GL20TU_REFLECTCUBE       , rsurface.texture->reflectcubetexture ? rsurface.texture->reflectcubetexture : r_texture_whitecube);
2945                 if (permutation & SHADERPERMUTATION_FOGHEIGHTTEXTURE) R_Mesh_TexBind(GL20TU_FOGHEIGHTTEXTURE  , r_texture_fogheighttexture                          );
2946                 if (permutation & (SHADERPERMUTATION_FOGINSIDE | SHADERPERMUTATION_FOGOUTSIDE)) R_Mesh_TexBind(GL20TU_FOGMASK           , r_texture_fogattenuation                            );
2947                 R_Mesh_TexBind(GL20TU_LIGHTMAP          , rsurface.lightmaptexture ? rsurface.lightmaptexture : r_texture_white);
2948                 R_Mesh_TexBind(GL20TU_DELUXEMAP         , rsurface.deluxemaptexture ? rsurface.deluxemaptexture : r_texture_blanknormalmap);
2949                 if (rsurface.rtlight                                  ) R_Mesh_TexBind(GL20TU_ATTENUATION       , r_shadow_attenuationgradienttexture                 );
2950                 if (rsurfacepass == RSURFPASS_BACKGROUND)
2951                 {
2952                         R_Mesh_TexBind(GL20TU_REFRACTION        , waterplane->texture_refraction ? waterplane->texture_refraction : r_texture_black);
2953                         if(mode == SHADERMODE_GENERIC) R_Mesh_TexBind(GL20TU_FIRST             , waterplane->texture_camera ? waterplane->texture_camera : r_texture_black);
2954                         R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2955                 }
2956                 else
2957                 {
2958                         if (permutation & SHADERPERMUTATION_REFLECTION        ) R_Mesh_TexBind(GL20TU_REFLECTION        , waterplane->texture_reflection ? waterplane->texture_reflection : r_texture_black);
2959                 }
2960 //              if (rsurfacepass == RSURFPASS_DEFERREDLIGHT           ) R_Mesh_TexBind(GL20TU_SCREENNORMALMAP   , r_shadow_prepassgeometrynormalmaptexture            );
2961                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENDIFFUSE     , r_shadow_prepasslightingdiffusetexture              );
2962                 if (permutation & SHADERPERMUTATION_DEFERREDLIGHTMAP  ) R_Mesh_TexBind(GL20TU_SCREENSPECULAR    , r_shadow_prepasslightingspeculartexture             );
2963                 if (rsurface.rtlight || (r_shadow_usingshadowmaportho && !(rsurface.ent_flags & RENDER_NOSELFSHADOW)))
2964                 {
2965                         R_Mesh_TexBind(GL20TU_SHADOWMAP2D, r_shadow_shadowmap2ddepthtexture);
2966                         if (rsurface.rtlight)
2967                         {
2968                                 if (permutation & SHADERPERMUTATION_CUBEFILTER        ) R_Mesh_TexBind(GL20TU_CUBE              , rsurface.rtlight->currentcubemap                    );
2969                                 if (permutation & SHADERPERMUTATION_SHADOWMAPVSDCT    ) R_Mesh_TexBind(GL20TU_CUBEPROJECTION    , r_shadow_shadowmapvsdcttexture                      );
2970                         }
2971                 }
2972                 break;
2973         }
2974 }
2975
2976 void R_SetupShader_DeferredLight(const rtlight_t *rtlight)
2977 {
2978         // select a permutation of the lighting shader appropriate to this
2979         // combination of texture, entity, light source, and fogging, only use the
2980         // minimum features necessary to avoid wasting rendering time in the
2981         // fragment shader on features that are not being used
2982         unsigned int permutation = 0;
2983         unsigned int mode = 0;
2984         const float *lightcolorbase = rtlight->currentcolor;
2985         float ambientscale = rtlight->ambientscale;
2986         float diffusescale = rtlight->diffusescale;
2987         float specularscale = rtlight->specularscale;
2988         // this is the location of the light in view space
2989         vec3_t viewlightorigin;
2990         // this transforms from view space (camera) to light space (cubemap)
2991         matrix4x4_t viewtolight;
2992         matrix4x4_t lighttoview;
2993         float viewtolight16f[16];
2994         // light source
2995         mode = SHADERMODE_DEFERREDLIGHTSOURCE;
2996         if (rtlight->currentcubemap != r_texture_whitecube)
2997                 permutation |= SHADERPERMUTATION_CUBEFILTER;
2998         if (diffusescale > 0)
2999                 permutation |= SHADERPERMUTATION_DIFFUSE;
3000         if (specularscale > 0 && r_shadow_gloss.integer > 0)
3001                 permutation |= SHADERPERMUTATION_SPECULAR | SHADERPERMUTATION_DIFFUSE;
3002         if (r_shadow_usingshadowmap2d)
3003         {
3004                 permutation |= SHADERPERMUTATION_SHADOWMAP2D;
3005                 if (r_shadow_shadowmapvsdct)
3006                         permutation |= SHADERPERMUTATION_SHADOWMAPVSDCT;
3007
3008                 if (r_shadow_shadowmap2ddepthbuffer)
3009                         permutation |= SHADERPERMUTATION_DEPTHRGB;
3010         }
3011         if (vid.allowalphatocoverage)
3012                 GL_AlphaToCoverage(false);
3013         Matrix4x4_Transform(&r_refdef.view.viewport.viewmatrix, rtlight->shadoworigin, viewlightorigin);
3014         Matrix4x4_Concat(&lighttoview, &r_refdef.view.viewport.viewmatrix, &rtlight->matrix_lighttoworld);
3015         Matrix4x4_Invert_Simple(&viewtolight, &lighttoview);
3016         Matrix4x4_ToArrayFloatGL(&viewtolight, viewtolight16f);
3017         switch(vid.renderpath)
3018         {
3019         case RENDERPATH_D3D9:
3020 #ifdef SUPPORTD3D
3021                 R_SetupShader_SetPermutationHLSL(mode, permutation);
3022                 hlslPSSetParameter3f(D3DPSREGISTER_LightPosition, viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3023                 hlslPSSetParameter16f(D3DPSREGISTER_ViewToLight, viewtolight16f);
3024                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Ambient , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3025                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Diffuse , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3026                 hlslPSSetParameter3f(D3DPSREGISTER_DeferredColor_Specular, lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3027                 hlslPSSetParameter2f(D3DPSREGISTER_ShadowMap_TextureScale, r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3028                 hlslPSSetParameter4f(D3DPSREGISTER_ShadowMap_Parameters, r_shadow_shadowmap_parameters[0], r_shadow_shadowmap_parameters[1], r_shadow_shadowmap_parameters[2], r_shadow_shadowmap_parameters[3]);
3029                 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);
3030                 hlslPSSetParameter2f(D3DPSREGISTER_ScreenToDepth, r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3031                 hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
3032
3033                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3034                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3035                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3036                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3037                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3038 #endif
3039                 break;
3040         case RENDERPATH_D3D10:
3041                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3042                 break;
3043         case RENDERPATH_D3D11:
3044                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
3045                 break;
3046         case RENDERPATH_GL20:
3047         case RENDERPATH_GLES2:
3048                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3049                 if (r_glsl_permutation->loc_LightPosition             >= 0) qglUniform3f(       r_glsl_permutation->loc_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3050                 if (r_glsl_permutation->loc_ViewToLight               >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ViewToLight              , 1, false, viewtolight16f);
3051                 if (r_glsl_permutation->loc_DeferredColor_Ambient     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3052                 if (r_glsl_permutation->loc_DeferredColor_Diffuse     >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3053                 if (r_glsl_permutation->loc_DeferredColor_Specular    >= 0) qglUniform3f(       r_glsl_permutation->loc_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3054                 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]);
3055                 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]);
3056                 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);
3057                 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]);
3058                 if (r_glsl_permutation->loc_PixelToScreenTexCoord     >= 0) qglUniform2f(       r_glsl_permutation->loc_PixelToScreenTexCoord    , 1.0f/vid.width, 1.0f/vid.height);
3059
3060                 if (r_glsl_permutation->tex_Texture_Attenuation       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Attenuation        , r_shadow_attenuationgradienttexture                 );
3061                 if (r_glsl_permutation->tex_Texture_ScreenNormalMap   >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ScreenNormalMap    , r_shadow_prepassgeometrynormalmaptexture            );
3062                 if (r_glsl_permutation->tex_Texture_Cube              >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Cube               , rsurface.rtlight->currentcubemap                    );
3063                 if (r_glsl_permutation->tex_Texture_ShadowMap2D       >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_ShadowMap2D        , r_shadow_shadowmap2ddepthtexture                    );
3064                 if (r_glsl_permutation->tex_Texture_CubeProjection    >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_CubeProjection     , r_shadow_shadowmapvsdcttexture                      );
3065                 break;
3066         case RENDERPATH_GL11:
3067         case RENDERPATH_GL13:
3068         case RENDERPATH_GLES1:
3069                 break;
3070         case RENDERPATH_SOFT:
3071                 R_SetupShader_SetPermutationGLSL(mode, permutation);
3072                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_LightPosition            , viewlightorigin[0], viewlightorigin[1], viewlightorigin[2]);
3073                 DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ViewToLightM1            , 1, false, viewtolight16f);
3074                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Ambient    , lightcolorbase[0] * ambientscale , lightcolorbase[1] * ambientscale , lightcolorbase[2] * ambientscale );
3075                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Diffuse    , lightcolorbase[0] * diffusescale , lightcolorbase[1] * diffusescale , lightcolorbase[2] * diffusescale );
3076                 DPSOFTRAST_Uniform3f(       DPSOFTRAST_UNIFORM_DeferredColor_Specular   , lightcolorbase[0] * specularscale, lightcolorbase[1] * specularscale, lightcolorbase[2] * specularscale);
3077                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ShadowMap_TextureScale   , r_shadow_shadowmap_texturescale[0], r_shadow_shadowmap_texturescale[1]);
3078                 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]);
3079                 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);
3080                 DPSOFTRAST_Uniform2f(       DPSOFTRAST_UNIFORM_ScreenToDepth            , r_refdef.view.viewport.screentodepth[0], r_refdef.view.viewport.screentodepth[1]);
3081                 DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
3082
3083                 R_Mesh_TexBind(GL20TU_ATTENUATION        , r_shadow_attenuationgradienttexture                 );
3084                 R_Mesh_TexBind(GL20TU_SCREENNORMALMAP    , r_shadow_prepassgeometrynormalmaptexture            );
3085                 R_Mesh_TexBind(GL20TU_CUBE               , rsurface.rtlight->currentcubemap                    );
3086                 R_Mesh_TexBind(GL20TU_SHADOWMAP2D        , r_shadow_shadowmap2ddepthtexture                    );
3087                 R_Mesh_TexBind(GL20TU_CUBEPROJECTION     , r_shadow_shadowmapvsdcttexture                      );
3088                 break;
3089         }
3090 }
3091
3092 #define SKINFRAME_HASH 1024
3093
3094 typedef struct
3095 {
3096         int loadsequence; // incremented each level change
3097         memexpandablearray_t array;
3098         skinframe_t *hash[SKINFRAME_HASH];
3099 }
3100 r_skinframe_t;
3101 r_skinframe_t r_skinframe;
3102
3103 void R_SkinFrame_PrepareForPurge(void)
3104 {
3105         r_skinframe.loadsequence++;
3106         // wrap it without hitting zero
3107         if (r_skinframe.loadsequence >= 200)
3108                 r_skinframe.loadsequence = 1;
3109 }
3110
3111 void R_SkinFrame_MarkUsed(skinframe_t *skinframe)
3112 {
3113         if (!skinframe)
3114                 return;
3115         // mark the skinframe as used for the purging code
3116         skinframe->loadsequence = r_skinframe.loadsequence;
3117 }
3118
3119 void R_SkinFrame_Purge(void)
3120 {
3121         int i;
3122         skinframe_t *s;
3123         for (i = 0;i < SKINFRAME_HASH;i++)
3124         {
3125                 for (s = r_skinframe.hash[i];s;s = s->next)
3126                 {
3127                         if (s->loadsequence && s->loadsequence != r_skinframe.loadsequence)
3128                         {
3129                                 if (s->merged == s->base)
3130                                         s->merged = NULL;
3131                                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3132                                 R_PurgeTexture(s->stain );s->stain  = NULL;
3133                                 R_PurgeTexture(s->merged);s->merged = NULL;
3134                                 R_PurgeTexture(s->base  );s->base   = NULL;
3135                                 R_PurgeTexture(s->pants );s->pants  = NULL;
3136                                 R_PurgeTexture(s->shirt );s->shirt  = NULL;
3137                                 R_PurgeTexture(s->nmap  );s->nmap   = NULL;
3138                                 R_PurgeTexture(s->gloss );s->gloss  = NULL;
3139                                 R_PurgeTexture(s->glow  );s->glow   = NULL;
3140                                 R_PurgeTexture(s->fog   );s->fog    = NULL;
3141                                 R_PurgeTexture(s->reflect);s->reflect = NULL;
3142                                 s->loadsequence = 0;
3143                         }
3144                 }
3145         }
3146 }
3147
3148 skinframe_t *R_SkinFrame_FindNextByName( skinframe_t *last, const char *name ) {
3149         skinframe_t *item;
3150         char basename[MAX_QPATH];
3151
3152         Image_StripImageExtension(name, basename, sizeof(basename));
3153
3154         if( last == NULL ) {
3155                 int hashindex;
3156                 hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3157                 item = r_skinframe.hash[hashindex];
3158         } else {
3159                 item = last->next;
3160         }
3161
3162         // linearly search through the hash bucket
3163         for( ; item ; item = item->next ) {
3164                 if( !strcmp( item->basename, basename ) ) {
3165                         return item;
3166                 }
3167         }
3168         return NULL;
3169 }
3170
3171 skinframe_t *R_SkinFrame_Find(const char *name, int textureflags, int comparewidth, int compareheight, int comparecrc, qboolean add)
3172 {
3173         skinframe_t *item;
3174         int hashindex;
3175         char basename[MAX_QPATH];
3176
3177         Image_StripImageExtension(name, basename, sizeof(basename));
3178
3179         hashindex = CRC_Block((unsigned char *)basename, strlen(basename)) & (SKINFRAME_HASH - 1);
3180         for (item = r_skinframe.hash[hashindex];item;item = item->next)
3181                 if (!strcmp(item->basename, basename) && (comparecrc < 0 || (item->textureflags == textureflags && item->comparewidth == comparewidth && item->compareheight == compareheight && item->comparecrc == comparecrc)))
3182                         break;
3183
3184         if (!item) {
3185                 rtexture_t *dyntexture;
3186                 // check whether its a dynamic texture
3187                 dyntexture = CL_GetDynTexture( basename );
3188                 if (!add && !dyntexture)
3189                         return NULL;
3190                 item = (skinframe_t *)Mem_ExpandableArray_AllocRecord(&r_skinframe.array);
3191                 memset(item, 0, sizeof(*item));
3192                 strlcpy(item->basename, basename, sizeof(item->basename));
3193                 item->base = dyntexture; // either NULL or dyntexture handle
3194                 item->textureflags = textureflags & ~TEXF_FORCE_RELOAD;
3195                 item->comparewidth = comparewidth;
3196                 item->compareheight = compareheight;
3197                 item->comparecrc = comparecrc;
3198                 item->next = r_skinframe.hash[hashindex];
3199                 r_skinframe.hash[hashindex] = item;
3200         }
3201         else if (textureflags & TEXF_FORCE_RELOAD)
3202         {
3203                 rtexture_t *dyntexture;
3204                 // check whether its a dynamic texture
3205                 dyntexture = CL_GetDynTexture( basename );
3206                 if (!add && !dyntexture)
3207                         return NULL;
3208                 if (item->merged == item->base)
3209                         item->merged = NULL;
3210                 // FIXME: maybe pass a pointer to the pointer to R_PurgeTexture and reset it to NULL inside? [11/29/2007 Black]
3211                 R_PurgeTexture(item->stain );item->stain  = NULL;
3212                 R_PurgeTexture(item->merged);item->merged = NULL;
3213                 R_PurgeTexture(item->base  );item->base   = NULL;
3214                 R_PurgeTexture(item->pants );item->pants  = NULL;
3215                 R_PurgeTexture(item->shirt );item->shirt  = NULL;
3216                 R_PurgeTexture(item->nmap  );item->nmap   = NULL;
3217                 R_PurgeTexture(item->gloss );item->gloss  = NULL;
3218                 R_PurgeTexture(item->glow  );item->glow   = NULL;
3219                 R_PurgeTexture(item->fog   );item->fog    = NULL;
3220         R_PurgeTexture(item->reflect);item->reflect = NULL;
3221                 item->loadsequence = 0;
3222         }
3223         else if( item->base == NULL )
3224         {
3225                 rtexture_t *dyntexture;
3226                 // check whether its a dynamic texture
3227                 // 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]
3228                 dyntexture = CL_GetDynTexture( basename );
3229                 item->base = dyntexture; // either NULL or dyntexture handle
3230         }
3231
3232         R_SkinFrame_MarkUsed(item);
3233         return item;
3234 }
3235
3236 #define R_SKINFRAME_LOAD_AVERAGE_COLORS(cnt, getpixel) \
3237         { \
3238                 unsigned long long avgcolor[5], wsum; \
3239                 int pix, comp, w; \
3240                 avgcolor[0] = 0; \
3241                 avgcolor[1] = 0; \
3242                 avgcolor[2] = 0; \
3243                 avgcolor[3] = 0; \
3244                 avgcolor[4] = 0; \
3245                 wsum = 0; \
3246                 for(pix = 0; pix < cnt; ++pix) \
3247                 { \
3248                         w = 0; \
3249                         for(comp = 0; comp < 3; ++comp) \
3250                                 w += getpixel; \
3251                         if(w) /* ignore perfectly black pixels because that is better for model skins */ \
3252                         { \
3253                                 ++wsum; \
3254                                 /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3255                                 w = getpixel; \
3256                                 for(comp = 0; comp < 3; ++comp) \
3257                                         avgcolor[comp] += getpixel * w; \
3258                                 avgcolor[3] += w; \
3259                         } \
3260                         /* comp = 3; -- not needed, comp is always 3 when we get here */ \
3261                         avgcolor[4] += getpixel; \
3262                 } \
3263                 if(avgcolor[3] == 0) /* no pixels seen? even worse */ \
3264                         avgcolor[3] = 1; \
3265                 skinframe->avgcolor[0] = avgcolor[2] / (255.0 * avgcolor[3]); \
3266                 skinframe->avgcolor[1] = avgcolor[1] / (255.0 * avgcolor[3]); \
3267                 skinframe->avgcolor[2] = avgcolor[0] / (255.0 * avgcolor[3]); \
3268                 skinframe->avgcolor[3] = avgcolor[4] / (255.0 * cnt); \
3269         }
3270
3271 extern cvar_t gl_picmip;
3272 skinframe_t *R_SkinFrame_LoadExternal(const char *name, int textureflags, qboolean complain)
3273 {
3274         int j;
3275         unsigned char *pixels;
3276         unsigned char *bumppixels;
3277         unsigned char *basepixels = NULL;
3278         int basepixels_width = 0;
3279         int basepixels_height = 0;
3280         skinframe_t *skinframe;
3281         rtexture_t *ddsbase = NULL;
3282         qboolean ddshasalpha = false;
3283         float ddsavgcolor[4];
3284         char basename[MAX_QPATH];
3285         int miplevel = R_PicmipForFlags(textureflags);
3286         int savemiplevel = miplevel;
3287         int mymiplevel;
3288         char vabuf[1024];
3289
3290         if (cls.state == ca_dedicated)
3291                 return NULL;
3292
3293         // return an existing skinframe if already loaded
3294         // if loading of the first image fails, don't make a new skinframe as it
3295         // would cause all future lookups of this to be missing
3296         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
3297         if (skinframe && skinframe->base)
3298                 return skinframe;
3299
3300         Image_StripImageExtension(name, basename, sizeof(basename));
3301
3302         // check for DDS texture file first
3303         if (!r_loaddds || !(ddsbase = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s.dds", basename), vid.sRGB3D, textureflags, &ddshasalpha, ddsavgcolor, miplevel)))
3304         {
3305                 basepixels = loadimagepixelsbgra(name, complain, true, false, &miplevel);
3306                 if (basepixels == NULL)
3307                         return NULL;
3308         }
3309
3310         // FIXME handle miplevel
3311
3312         if (developer_loading.integer)
3313                 Con_Printf("loading skin \"%s\"\n", name);
3314
3315         // we've got some pixels to store, so really allocate this new texture now
3316         if (!skinframe)
3317                 skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, true);
3318         textureflags &= ~TEXF_FORCE_RELOAD;
3319         skinframe->stain = NULL;
3320         skinframe->merged = NULL;
3321         skinframe->base = NULL;
3322         skinframe->pants = NULL;
3323         skinframe->shirt = NULL;
3324         skinframe->nmap = NULL;
3325         skinframe->gloss = NULL;
3326         skinframe->glow = NULL;
3327         skinframe->fog = NULL;
3328         skinframe->reflect = NULL;
3329         skinframe->hasalpha = false;
3330
3331         if (ddsbase)
3332         {
3333                 skinframe->base = ddsbase;
3334                 skinframe->hasalpha = ddshasalpha;
3335                 VectorCopy(ddsavgcolor, skinframe->avgcolor);
3336                 if (r_loadfog && skinframe->hasalpha)
3337                         skinframe->fog = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), false, textureflags | TEXF_ALPHA, NULL, NULL, miplevel);
3338                 //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]);
3339         }
3340         else
3341         {
3342                 basepixels_width = image_width;
3343                 basepixels_height = image_height;
3344                 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);
3345                 if (textureflags & TEXF_ALPHA)
3346                 {
3347                         for (j = 3;j < basepixels_width * basepixels_height * 4;j += 4)
3348                         {
3349                                 if (basepixels[j] < 255)
3350                                 {
3351                                         skinframe->hasalpha = true;
3352                                         break;
3353                                 }
3354                         }
3355                         if (r_loadfog && skinframe->hasalpha)
3356                         {
3357                                 // has transparent pixels
3358                                 pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3359                                 for (j = 0;j < image_width * image_height * 4;j += 4)
3360                                 {
3361                                         pixels[j+0] = 255;
3362                                         pixels[j+1] = 255;
3363                                         pixels[j+2] = 255;
3364                                         pixels[j+3] = basepixels[j+3];
3365                                 }
3366                                 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);
3367                                 Mem_Free(pixels);
3368                         }
3369                 }
3370                 R_SKINFRAME_LOAD_AVERAGE_COLORS(basepixels_width * basepixels_height, basepixels[4 * pix + comp]);
3371 #ifndef USE_GLES2
3372                 //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]);
3373                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->base)
3374                         R_SaveTextureDDSFile(skinframe->base, va(vabuf, sizeof(vabuf), "dds/%s.dds", skinframe->basename), r_texture_dds_save.integer < 2, skinframe->hasalpha);
3375                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->fog)
3376                         R_SaveTextureDDSFile(skinframe->fog, va(vabuf, sizeof(vabuf), "dds/%s_mask.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3377 #endif
3378         }
3379
3380         if (r_loaddds)
3381         {
3382                 mymiplevel = savemiplevel;
3383                 if (r_loadnormalmap)
3384                         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);
3385                 skinframe->glow = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3386                 if (r_loadgloss)
3387                         skinframe->gloss = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3388                 skinframe->pants = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3389                 skinframe->shirt = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3390                 skinframe->reflect = R_LoadTextureDDSFile(r_main_texturepool, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), vid.sRGB3D, textureflags, NULL, NULL, mymiplevel);
3391         }
3392
3393         // _norm is the name used by tenebrae and has been adopted as standard
3394         if (r_loadnormalmap && skinframe->nmap == NULL)
3395         {
3396                 mymiplevel = savemiplevel;
3397                 if ((pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_norm", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3398                 {
3399                         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);
3400                         Mem_Free(pixels);
3401                         pixels = NULL;
3402                 }
3403                 else if (r_shadow_bumpscale_bumpmap.value > 0 && (bumppixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_bump", skinframe->basename), false, false, false, &mymiplevel)) != NULL)
3404                 {
3405                         pixels = (unsigned char *)Mem_Alloc(tempmempool, image_width * image_height * 4);
3406                         Image_HeightmapToNormalmap_BGRA(bumppixels, pixels, image_width, image_height, false, r_shadow_bumpscale_bumpmap.value);
3407                         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);
3408                         Mem_Free(pixels);
3409                         Mem_Free(bumppixels);
3410                 }
3411                 else if (r_shadow_bumpscale_basetexture.value > 0)
3412                 {
3413                         pixels = (unsigned char *)Mem_Alloc(tempmempool, basepixels_width * basepixels_height * 4);
3414                         Image_HeightmapToNormalmap_BGRA(basepixels, pixels, basepixels_width, basepixels_height, false, r_shadow_bumpscale_basetexture.value);
3415                         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);
3416                         Mem_Free(pixels);
3417                 }
3418 #ifndef USE_GLES2
3419                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->nmap)
3420                         R_SaveTextureDDSFile(skinframe->nmap, va(vabuf, sizeof(vabuf), "dds/%s_norm.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3421 #endif
3422         }
3423
3424         // _luma is supported only for tenebrae compatibility
3425         // _glow is the preferred name
3426         mymiplevel = savemiplevel;
3427         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))))
3428         {
3429                 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);
3430 #ifndef USE_GLES2
3431                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->glow)
3432                         R_SaveTextureDDSFile(skinframe->glow, va(vabuf, sizeof(vabuf), "dds/%s_glow.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3433 #endif
3434                 Mem_Free(pixels);pixels = NULL;
3435         }
3436
3437         mymiplevel = savemiplevel;
3438         if (skinframe->gloss == NULL && r_loadgloss && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_gloss", skinframe->basename), false, false, false, &mymiplevel)))
3439         {
3440                 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);
3441 #ifndef USE_GLES2
3442                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->gloss)
3443                         R_SaveTextureDDSFile(skinframe->gloss, va(vabuf, sizeof(vabuf), "dds/%s_gloss.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3444 #endif
3445                 Mem_Free(pixels);
3446                 pixels = NULL;
3447         }
3448
3449         mymiplevel = savemiplevel;
3450         if (skinframe->pants == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_pants", skinframe->basename), false, false, false, &mymiplevel)))
3451         {
3452                 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);
3453 #ifndef USE_GLES2
3454                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->pants)
3455                         R_SaveTextureDDSFile(skinframe->pants, va(vabuf, sizeof(vabuf), "dds/%s_pants.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3456 #endif
3457                 Mem_Free(pixels);
3458                 pixels = NULL;
3459         }
3460
3461         mymiplevel = savemiplevel;
3462         if (skinframe->shirt == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_shirt", skinframe->basename), false, false, false, &mymiplevel)))
3463         {
3464                 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);
3465 #ifndef USE_GLES2
3466                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->shirt)
3467                         R_SaveTextureDDSFile(skinframe->shirt, va(vabuf, sizeof(vabuf), "dds/%s_shirt.dds", skinframe->basename), r_texture_dds_save.integer < 2, false);
3468 #endif
3469                 Mem_Free(pixels);
3470                 pixels = NULL;
3471         }
3472
3473         mymiplevel = savemiplevel;
3474         if (skinframe->reflect == NULL && (pixels = loadimagepixelsbgra(va(vabuf, sizeof(vabuf), "%s_reflect", skinframe->basename), false, false, false, &mymiplevel)))
3475         {
3476                 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);
3477 #ifndef USE_GLES2
3478                 if (r_savedds && qglGetCompressedTexImageARB && skinframe->reflect)
3479                         R_SaveTextureDDSFile(skinframe->reflect, va(vabuf, sizeof(vabuf), "dds/%s_reflect.dds", skinframe->basename), r_texture_dds_save.integer < 2, true);
3480 #endif
3481                 Mem_Free(pixels);
3482                 pixels = NULL;
3483         }
3484
3485         if (basepixels)
3486                 Mem_Free(basepixels);
3487
3488         return skinframe;
3489 }
3490
3491 // this is only used by .spr32 sprites, HL .spr files, HL .bsp files
3492 skinframe_t *R_SkinFrame_LoadInternalBGRA(const char *name, int textureflags, const unsigned char *skindata, int width, int height, qboolean sRGB)
3493 {
3494         int i;
3495         unsigned char *temp1, *temp2;
3496         skinframe_t *skinframe;
3497         char vabuf[1024];
3498
3499         if (cls.state == ca_dedicated)
3500                 return NULL;
3501
3502         // if already loaded just return it, otherwise make a new skinframe
3503         skinframe = R_SkinFrame_Find(name, textureflags, width, height, (textureflags & TEXF_FORCE_RELOAD) ? -1 : skindata ? CRC_Block(skindata, width*height*4) : 0, true);
3504         if (skinframe && skinframe->base)
3505                 return skinframe;
3506         textureflags &= ~TEXF_FORCE_RELOAD;
3507
3508         skinframe->stain = NULL;
3509         skinframe->merged = NULL;
3510         skinframe->base = NULL;
3511         skinframe->pants = NULL;
3512         skinframe->shirt = NULL;
3513         skinframe->nmap = NULL;
3514         skinframe->gloss = NULL;
3515         skinframe->glow = NULL;
3516         skinframe->fog = NULL;
3517         skinframe->reflect = NULL;
3518         skinframe->hasalpha = false;
3519
3520         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3521         if (!skindata)
3522                 return NULL;
3523
3524         if (developer_loading.integer)
3525                 Con_Printf("loading 32bit skin \"%s\"\n", name);
3526
3527         if (r_loadnormalmap && r_shadow_bumpscale_basetexture.value > 0)
3528         {
3529                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3530                 temp2 = temp1 + width * height * 4;
3531                 Image_HeightmapToNormalmap_BGRA(skindata, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3532                 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);
3533                 Mem_Free(temp1);
3534         }
3535         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, sRGB ? TEXTYPE_SRGB_BGRA : TEXTYPE_BGRA, textureflags, -1, NULL);
3536         if (textureflags & TEXF_ALPHA)
3537         {
3538                 for (i = 3;i < width * height * 4;i += 4)
3539                 {
3540                         if (skindata[i] < 255)
3541                         {
3542                                 skinframe->hasalpha = true;
3543                                 break;
3544                         }
3545                 }
3546                 if (r_loadfog && skinframe->hasalpha)
3547                 {
3548                         unsigned char *fogpixels = (unsigned char *)Mem_Alloc(tempmempool, width * height * 4);
3549                         memcpy(fogpixels, skindata, width * height * 4);
3550                         for (i = 0;i < width * height * 4;i += 4)
3551                                 fogpixels[i] = fogpixels[i+1] = fogpixels[i+2] = 255;
3552                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, fogpixels, TEXTYPE_BGRA, textureflags, -1, NULL);
3553                         Mem_Free(fogpixels);
3554                 }
3555         }
3556
3557         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, skindata[4 * pix + comp]);
3558         //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]);
3559
3560         return skinframe;
3561 }
3562
3563 skinframe_t *R_SkinFrame_LoadInternalQuake(const char *name, int textureflags, int loadpantsandshirt, int loadglowtexture, const unsigned char *skindata, int width, int height)
3564 {
3565         int i;
3566         int featuresmask;
3567         skinframe_t *skinframe;
3568
3569         if (cls.state == ca_dedicated)
3570                 return NULL;
3571
3572         // if already loaded just return it, otherwise make a new skinframe
3573         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3574         if (skinframe && skinframe->base)
3575                 return skinframe;
3576         textureflags &= ~TEXF_FORCE_RELOAD;
3577
3578         skinframe->stain = NULL;
3579         skinframe->merged = NULL;
3580         skinframe->base = NULL;
3581         skinframe->pants = NULL;
3582         skinframe->shirt = NULL;
3583         skinframe->nmap = NULL;
3584         skinframe->gloss = NULL;
3585         skinframe->glow = NULL;
3586         skinframe->fog = NULL;
3587         skinframe->reflect = NULL;
3588         skinframe->hasalpha = false;
3589
3590         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3591         if (!skindata)
3592                 return NULL;
3593
3594         if (developer_loading.integer)
3595                 Con_Printf("loading quake skin \"%s\"\n", name);
3596
3597         // 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)
3598         skinframe->qpixels = (unsigned char *)Mem_Alloc(r_main_mempool, width*height); // FIXME LEAK
3599         memcpy(skinframe->qpixels, skindata, width*height);
3600         skinframe->qwidth = width;
3601         skinframe->qheight = height;
3602
3603         featuresmask = 0;
3604         for (i = 0;i < width * height;i++)
3605                 featuresmask |= palette_featureflags[skindata[i]];
3606
3607         skinframe->hasalpha = false;
3608         skinframe->qhascolormapping = loadpantsandshirt && (featuresmask & (PALETTEFEATURE_PANTS | PALETTEFEATURE_SHIRT));
3609         skinframe->qgeneratenmap = r_shadow_bumpscale_basetexture.value > 0;
3610         skinframe->qgeneratemerged = true;
3611         skinframe->qgeneratebase = skinframe->qhascolormapping;
3612         skinframe->qgenerateglow = loadglowtexture && (featuresmask & PALETTEFEATURE_GLOW);
3613
3614         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette_bgra_complete)[skindata[pix]*4 + comp]);
3615         //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]);
3616
3617         return skinframe;
3618 }
3619
3620 static void R_SkinFrame_GenerateTexturesFromQPixels(skinframe_t *skinframe, qboolean colormapped)
3621 {
3622         int width;
3623         int height;
3624         unsigned char *skindata;
3625         char vabuf[1024];
3626
3627         if (!skinframe->qpixels)
3628                 return;
3629
3630         if (!skinframe->qhascolormapping)
3631                 colormapped = false;
3632
3633         if (colormapped)
3634         {
3635                 if (!skinframe->qgeneratebase)
3636                         return;
3637         }
3638         else
3639         {
3640                 if (!skinframe->qgeneratemerged)
3641                         return;
3642         }
3643
3644         width = skinframe->qwidth;
3645         height = skinframe->qheight;
3646         skindata = skinframe->qpixels;
3647
3648         if (skinframe->qgeneratenmap)
3649         {
3650                 unsigned char *temp1, *temp2;
3651                 skinframe->qgeneratenmap = false;
3652                 temp1 = (unsigned char *)Mem_Alloc(tempmempool, width * height * 8);
3653                 temp2 = temp1 + width * height * 4;
3654                 // use either a custom palette or the quake palette
3655                 Image_Copy8bitBGRA(skindata, temp1, width * height, palette_bgra_complete);
3656                 Image_HeightmapToNormalmap_BGRA(temp1, temp2, width, height, false, r_shadow_bumpscale_basetexture.value);
3657                 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);
3658                 Mem_Free(temp1);
3659         }
3660
3661         if (skinframe->qgenerateglow)
3662         {
3663                 skinframe->qgenerateglow = false;
3664                 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
3665         }
3666
3667         if (colormapped)
3668         {
3669                 skinframe->qgeneratebase = false;
3670                 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);
3671                 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);
3672                 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);
3673         }
3674         else
3675         {
3676                 skinframe->qgeneratemerged = false;
3677                 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);
3678         }
3679
3680         if (!skinframe->qgeneratemerged && !skinframe->qgeneratebase)
3681         {
3682                 Mem_Free(skinframe->qpixels);
3683                 skinframe->qpixels = NULL;
3684         }
3685 }
3686
3687 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)
3688 {
3689         int i;
3690         skinframe_t *skinframe;
3691         char vabuf[1024];
3692
3693         if (cls.state == ca_dedicated)
3694                 return NULL;
3695
3696         // if already loaded just return it, otherwise make a new skinframe
3697         skinframe = R_SkinFrame_Find(name, textureflags, width, height, skindata ? CRC_Block(skindata, width*height) : 0, true);
3698         if (skinframe && skinframe->base)
3699                 return skinframe;
3700         textureflags &= ~TEXF_FORCE_RELOAD;
3701
3702         skinframe->stain = NULL;
3703         skinframe->merged = NULL;
3704         skinframe->base = NULL;
3705         skinframe->pants = NULL;
3706         skinframe->shirt = NULL;
3707         skinframe->nmap = NULL;
3708         skinframe->gloss = NULL;
3709         skinframe->glow = NULL;
3710         skinframe->fog = NULL;
3711         skinframe->reflect = NULL;
3712         skinframe->hasalpha = false;
3713
3714         // if no data was provided, then clearly the caller wanted to get a blank skinframe
3715         if (!skindata)
3716                 return NULL;
3717
3718         if (developer_loading.integer)
3719                 Con_Printf("loading embedded 8bit image \"%s\"\n", name);
3720
3721         skinframe->base = skinframe->merged = R_LoadTexture2D(r_main_texturepool, skinframe->basename, width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, palette);
3722         if (textureflags & TEXF_ALPHA)
3723         {
3724                 for (i = 0;i < width * height;i++)
3725                 {
3726                         if (((unsigned char *)palette)[skindata[i]*4+3] < 255)
3727                         {
3728                                 skinframe->hasalpha = true;
3729                                 break;
3730                         }
3731                 }
3732                 if (r_loadfog && skinframe->hasalpha)
3733                         skinframe->fog = R_LoadTexture2D(r_main_texturepool, va(vabuf, sizeof(vabuf), "%s_fog", skinframe->basename), width, height, skindata, TEXTYPE_PALETTE, textureflags, -1, alphapalette);
3734         }
3735
3736         R_SKINFRAME_LOAD_AVERAGE_COLORS(width * height, ((unsigned char *)palette)[skindata[pix]*4 + comp]);
3737         //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]);
3738
3739         return skinframe;
3740 }
3741
3742 skinframe_t *R_SkinFrame_LoadMissing(void)
3743 {
3744         skinframe_t *skinframe;
3745
3746         if (cls.state == ca_dedicated)
3747                 return NULL;
3748
3749         skinframe = R_SkinFrame_Find("missing", TEXF_FORCENEAREST, 0, 0, 0, true);
3750         skinframe->stain = NULL;
3751         skinframe->merged = NULL;
3752         skinframe->base = NULL;
3753         skinframe->pants = NULL;
3754         skinframe->shirt = NULL;
3755         skinframe->nmap = NULL;
3756         skinframe->gloss = NULL;
3757         skinframe->glow = NULL;
3758         skinframe->fog = NULL;
3759         skinframe->reflect = NULL;
3760         skinframe->hasalpha = false;
3761
3762         skinframe->avgcolor[0] = rand() / RAND_MAX;
3763         skinframe->avgcolor[1] = rand() / RAND_MAX;
3764         skinframe->avgcolor[2] = rand() / RAND_MAX;
3765         skinframe->avgcolor[3] = 1;
3766
3767         return skinframe;
3768 }
3769
3770 //static char *suffix[6] = {"ft", "bk", "rt", "lf", "up", "dn"};
3771 typedef struct suffixinfo_s
3772 {
3773         const char *suffix;
3774         qboolean flipx, flipy, flipdiagonal;
3775 }
3776 suffixinfo_t;
3777 static suffixinfo_t suffix[3][6] =
3778 {
3779         {
3780                 {"px",   false, false, false},
3781                 {"nx",   false, false, false},
3782                 {"py",   false, false, false},
3783                 {"ny",   false, false, false},
3784                 {"pz",   false, false, false},
3785                 {"nz",   false, false, false}
3786         },
3787         {
3788                 {"posx", false, false, false},
3789                 {"negx", false, false, false},
3790                 {"posy", false, false, false},
3791                 {"negy", false, false, false},
3792                 {"posz", false, false, false},
3793                 {"negz", false, false, false}
3794         },
3795         {
3796                 {"rt",    true, false,  true},
3797                 {"lf",   false,  true,  true},
3798                 {"ft",    true,  true, false},
3799                 {"bk",   false, false, false},
3800                 {"up",    true, false,  true},
3801                 {"dn",    true, false,  true}
3802         }
3803 };
3804
3805 static int componentorder[4] = {0, 1, 2, 3};
3806
3807 static rtexture_t *R_LoadCubemap(const char *basename)
3808 {
3809         int i, j, cubemapsize;
3810         unsigned char *cubemappixels, *image_buffer;
3811         rtexture_t *cubemaptexture;
3812         char name[256];
3813         // must start 0 so the first loadimagepixels has no requested width/height
3814         cubemapsize = 0;
3815         cubemappixels = NULL;
3816         cubemaptexture = NULL;
3817         // keep trying different suffix groups (posx, px, rt) until one loads
3818         for (j = 0;j < 3 && !cubemappixels;j++)
3819         {
3820                 // load the 6 images in the suffix group
3821                 for (i = 0;i < 6;i++)
3822                 {
3823                         // generate an image name based on the base and and suffix
3824                         dpsnprintf(name, sizeof(name), "%s%s", basename, suffix[j][i].suffix);
3825                         // load it
3826                         if ((image_buffer = loadimagepixelsbgra(name, false, false, false, NULL)))
3827                         {
3828                                 // an image loaded, make sure width and height are equal
3829                                 if (image_width == image_height && (!cubemappixels || image_width == cubemapsize))
3830                                 {
3831                                         // if this is the first image to load successfully, allocate the cubemap memory
3832                                         if (!cubemappixels && image_width >= 1)
3833                                         {
3834                                                 cubemapsize = image_width;
3835                                                 // note this clears to black, so unavailable sides are black
3836                                                 cubemappixels = (unsigned char *)Mem_Alloc(tempmempool, 6*cubemapsize*cubemapsize*4);
3837                                         }
3838                                         // copy the image with any flipping needed by the suffix (px and posx types don't need flipping)
3839                                         if (cubemappixels)
3840                                                 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);
3841                                 }
3842                                 else
3843                                         Con_Printf("Cubemap image \"%s\" (%ix%i) is not square, OpenGL requires square cubemaps.\n", name, image_width, image_height);
3844                                 // free the image
3845                                 Mem_Free(image_buffer);
3846                         }
3847                 }
3848         }
3849         // if a cubemap loaded, upload it
3850         if (cubemappixels)
3851         {
3852                 if (developer_loading.integer)
3853                         Con_Printf("loading cubemap \"%s\"\n", basename);
3854
3855                 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);
3856                 Mem_Free(cubemappixels);
3857         }
3858         else
3859         {
3860                 Con_DPrintf("failed to load cubemap \"%s\"\n", basename);
3861                 if (developer_loading.integer)
3862                 {
3863                         Con_Printf("(tried tried images ");
3864                         for (j = 0;j < 3;j++)
3865                                 for (i = 0;i < 6;i++)
3866                                         Con_Printf("%s\"%s%s.tga\"", j + i > 0 ? ", " : "", basename, suffix[j][i].suffix);
3867                         Con_Print(" and was unable to find any of them).\n");
3868                 }
3869         }
3870         return cubemaptexture;
3871 }
3872
3873 rtexture_t *R_GetCubemap(const char *basename)
3874 {
3875         int i;
3876         for (i = 0;i < r_texture_numcubemaps;i++)
3877                 if (r_texture_cubemaps[i] != NULL)
3878                         if (!strcasecmp(r_texture_cubemaps[i]->basename, basename))
3879                                 return r_texture_cubemaps[i]->texture ? r_texture_cubemaps[i]->texture : r_texture_whitecube;
3880         if (i >= MAX_CUBEMAPS || !r_main_mempool)
3881                 return r_texture_whitecube;
3882         r_texture_numcubemaps++;
3883         r_texture_cubemaps[i] = (cubemapinfo_t *)Mem_Alloc(r_main_mempool, sizeof(cubemapinfo_t));
3884         strlcpy(r_texture_cubemaps[i]->basename, basename, sizeof(r_texture_cubemaps[i]->basename));
3885         r_texture_cubemaps[i]->texture = R_LoadCubemap(r_texture_cubemaps[i]->basename);
3886         return r_texture_cubemaps[i]->texture;
3887 }
3888
3889 static void R_Main_FreeViewCache(void)
3890 {
3891         if (r_refdef.viewcache.entityvisible)
3892                 Mem_Free(r_refdef.viewcache.entityvisible);
3893         if (r_refdef.viewcache.world_pvsbits)
3894                 Mem_Free(r_refdef.viewcache.world_pvsbits);
3895         if (r_refdef.viewcache.world_leafvisible)
3896                 Mem_Free(r_refdef.viewcache.world_leafvisible);
3897         if (r_refdef.viewcache.world_surfacevisible)
3898                 Mem_Free(r_refdef.viewcache.world_surfacevisible);
3899         memset(&r_refdef.viewcache, 0, sizeof(r_refdef.viewcache));
3900 }
3901
3902 static void R_Main_ResizeViewCache(void)
3903 {
3904         int numentities = r_refdef.scene.numentities;
3905         int numclusters = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusters : 1;
3906         int numclusterbytes = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_pvsclusterbytes : 1;
3907         int numleafs = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->brush.num_leafs : 1;
3908         int numsurfaces = r_refdef.scene.worldmodel ? r_refdef.scene.worldmodel->num_surfaces : 1;
3909         if (r_refdef.viewcache.maxentities < numentities)
3910         {
3911                 r_refdef.viewcache.maxentities = numentities;
3912                 if (r_refdef.viewcache.entityvisible)
3913                         Mem_Free(r_refdef.viewcache.entityvisible);
3914                 r_refdef.viewcache.entityvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.maxentities);
3915         }
3916         if (r_refdef.viewcache.world_numclusters != numclusters)
3917         {
3918                 r_refdef.viewcache.world_numclusters = numclusters;
3919                 r_refdef.viewcache.world_numclusterbytes = numclusterbytes;
3920                 if (r_refdef.viewcache.world_pvsbits)
3921                         Mem_Free(r_refdef.viewcache.world_pvsbits);
3922                 r_refdef.viewcache.world_pvsbits = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numclusterbytes);
3923         }
3924         if (r_refdef.viewcache.world_numleafs != numleafs)
3925         {
3926                 r_refdef.viewcache.world_numleafs = numleafs;
3927                 if (r_refdef.viewcache.world_leafvisible)
3928                         Mem_Free(r_refdef.viewcache.world_leafvisible);
3929                 r_refdef.viewcache.world_leafvisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numleafs);
3930         }
3931         if (r_refdef.viewcache.world_numsurfaces != numsurfaces)
3932         {
3933                 r_refdef.viewcache.world_numsurfaces = numsurfaces;
3934                 if (r_refdef.viewcache.world_surfacevisible)
3935                         Mem_Free(r_refdef.viewcache.world_surfacevisible);
3936                 r_refdef.viewcache.world_surfacevisible = (unsigned char *)Mem_Alloc(r_main_mempool, r_refdef.viewcache.world_numsurfaces);
3937         }
3938 }
3939
3940 extern rtexture_t *loadingscreentexture;
3941 static void gl_main_start(void)
3942 {
3943         loadingscreentexture = NULL;
3944         r_texture_blanknormalmap = NULL;
3945         r_texture_white = NULL;
3946         r_texture_grey128 = NULL;
3947         r_texture_black = NULL;
3948         r_texture_whitecube = NULL;
3949         r_texture_normalizationcube = NULL;
3950         r_texture_fogattenuation = NULL;
3951         r_texture_fogheighttexture = NULL;
3952         r_texture_gammaramps = NULL;
3953         r_texture_numcubemaps = 0;
3954
3955         r_loaddds = r_texture_dds_load.integer != 0;
3956         r_savedds = vid.support.arb_texture_compression && vid.support.ext_texture_compression_s3tc && r_texture_dds_save.integer;
3957
3958         switch(vid.renderpath)
3959         {
3960         case RENDERPATH_GL20:
3961         case RENDERPATH_D3D9:
3962         case RENDERPATH_D3D10:
3963         case RENDERPATH_D3D11:
3964         case RENDERPATH_SOFT:
3965         case RENDERPATH_GLES2:
3966                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3967                 Cvar_SetValueQuick(&gl_combine, 1);
3968                 Cvar_SetValueQuick(&r_glsl, 1);
3969                 r_loadnormalmap = true;
3970                 r_loadgloss = true;
3971                 r_loadfog = false;
3972                 break;
3973         case RENDERPATH_GL13:
3974         case RENDERPATH_GLES1:
3975                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3976                 Cvar_SetValueQuick(&gl_combine, 1);
3977                 Cvar_SetValueQuick(&r_glsl, 0);
3978                 r_loadnormalmap = false;
3979                 r_loadgloss = false;
3980                 r_loadfog = true;
3981                 break;
3982         case RENDERPATH_GL11:
3983                 Cvar_SetValueQuick(&r_textureunits, vid.texunits);
3984                 Cvar_SetValueQuick(&gl_combine, 0);
3985                 Cvar_SetValueQuick(&r_glsl, 0);
3986                 r_loadnormalmap = false;
3987                 r_loadgloss = false;
3988                 r_loadfog = true;
3989                 break;
3990         }
3991
3992         R_AnimCache_Free();
3993         R_FrameData_Reset();
3994
3995         r_numqueries = 0;
3996         r_maxqueries = 0;
3997         memset(r_queries, 0, sizeof(r_queries));
3998
3999         r_qwskincache = NULL;
4000         r_qwskincache_size = 0;
4001
4002         // due to caching of texture_t references, the collision cache must be reset
4003         Collision_Cache_Reset(true);
4004
4005         // set up r_skinframe loading system for textures
4006         memset(&r_skinframe, 0, sizeof(r_skinframe));
4007         r_skinframe.loadsequence = 1;
4008         Mem_ExpandableArray_NewArray(&r_skinframe.array, r_main_mempool, sizeof(skinframe_t), 256);
4009
4010         r_main_texturepool = R_AllocTexturePool();
4011         R_BuildBlankTextures();
4012         R_BuildNoTexture();
4013         if (vid.support.arb_texture_cube_map)
4014         {
4015                 R_BuildWhiteCube();
4016                 R_BuildNormalizationCube();
4017         }
4018         r_texture_fogattenuation = NULL;
4019         r_texture_fogheighttexture = NULL;
4020         r_texture_gammaramps = NULL;
4021         //r_texture_fogintensity = NULL;
4022         memset(&r_fb, 0, sizeof(r_fb));
4023         r_glsl_permutation = NULL;
4024         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4025         Mem_ExpandableArray_NewArray(&r_glsl_permutationarray, r_main_mempool, sizeof(r_glsl_permutation_t), 256);
4026         glslshaderstring = NULL;
4027 #ifdef SUPPORTD3D
4028         r_hlsl_permutation = NULL;
4029         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4030         Mem_ExpandableArray_NewArray(&r_hlsl_permutationarray, r_main_mempool, sizeof(r_hlsl_permutation_t), 256);
4031 #endif
4032         hlslshaderstring = NULL;
4033         memset(&r_svbsp, 0, sizeof (r_svbsp));
4034
4035         memset(r_texture_cubemaps, 0, sizeof(r_texture_cubemaps));
4036         r_texture_numcubemaps = 0;
4037
4038         r_refdef.fogmasktable_density = 0;
4039 }
4040
4041 static void gl_main_shutdown(void)
4042 {
4043         R_AnimCache_Free();
4044         R_FrameData_Reset();
4045
4046         R_Main_FreeViewCache();
4047
4048         switch(vid.renderpath)
4049         {
4050         case RENDERPATH_GL11:
4051         case RENDERPATH_GL13:
4052         case RENDERPATH_GL20:
4053         case RENDERPATH_GLES1:
4054         case RENDERPATH_GLES2:
4055 #ifdef GL_SAMPLES_PASSED_ARB
4056                 if (r_maxqueries)
4057                         qglDeleteQueriesARB(r_maxqueries, r_queries);
4058 #endif
4059                 break;
4060         case RENDERPATH_D3D9:
4061                 //Con_DPrintf("FIXME D3D9 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4062                 break;
4063         case RENDERPATH_D3D10:
4064                 Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4065                 break;
4066         case RENDERPATH_D3D11:
4067                 Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
4068                 break;
4069         case RENDERPATH_SOFT:
4070                 break;
4071         }
4072
4073         r_numqueries = 0;
4074         r_maxqueries = 0;
4075         memset(r_queries, 0, sizeof(r_queries));
4076
4077         r_qwskincache = NULL;
4078         r_qwskincache_size = 0;
4079
4080         // clear out the r_skinframe state
4081         Mem_ExpandableArray_FreeArray(&r_skinframe.array);
4082         memset(&r_skinframe, 0, sizeof(r_skinframe));
4083
4084         if (r_svbsp.nodes)
4085                 Mem_Free(r_svbsp.nodes);
4086         memset(&r_svbsp, 0, sizeof (r_svbsp));
4087         R_FreeTexturePool(&r_main_texturepool);
4088         loadingscreentexture = NULL;
4089         r_texture_blanknormalmap = NULL;
4090         r_texture_white = NULL;
4091         r_texture_grey128 = NULL;
4092         r_texture_black = NULL;
4093         r_texture_whitecube = NULL;
4094         r_texture_normalizationcube = NULL;
4095         r_texture_fogattenuation = NULL;
4096         r_texture_fogheighttexture = NULL;
4097         r_texture_gammaramps = NULL;
4098         r_texture_numcubemaps = 0;
4099         //r_texture_fogintensity = NULL;
4100         memset(&r_fb, 0, sizeof(r_fb));
4101         R_GLSL_Restart_f();
4102
4103         r_glsl_permutation = NULL;
4104         memset(r_glsl_permutationhash, 0, sizeof(r_glsl_permutationhash));
4105         Mem_ExpandableArray_FreeArray(&r_glsl_permutationarray);
4106         glslshaderstring = NULL;
4107 #ifdef SUPPORTD3D
4108         r_hlsl_permutation = NULL;
4109         memset(r_hlsl_permutationhash, 0, sizeof(r_hlsl_permutationhash));
4110         Mem_ExpandableArray_FreeArray(&r_hlsl_permutationarray);
4111 #endif
4112         hlslshaderstring = NULL;
4113 }
4114
4115 static void gl_main_newmap(void)
4116 {
4117         // FIXME: move this code to client
4118         char *entities, entname[MAX_QPATH];
4119         if (r_qwskincache)
4120                 Mem_Free(r_qwskincache);
4121         r_qwskincache = NULL;
4122         r_qwskincache_size = 0;
4123         if (cl.worldmodel)
4124         {
4125                 dpsnprintf(entname, sizeof(entname), "%s.ent", cl.worldnamenoextension);
4126                 if ((entities = (char *)FS_LoadFile(entname, tempmempool, true, NULL)))
4127                 {
4128                         CL_ParseEntityLump(entities);
4129                         Mem_Free(entities);
4130                         return;
4131                 }
4132                 if (cl.worldmodel->brush.entities)
4133                         CL_ParseEntityLump(cl.worldmodel->brush.entities);
4134         }
4135         R_Main_FreeViewCache();
4136
4137         R_FrameData_Reset();
4138 }
4139
4140 void GL_Main_Init(void)
4141 {
4142         r_main_mempool = Mem_AllocPool("Renderer", 0, NULL);
4143
4144         Cmd_AddCommand("r_glsl_restart", R_GLSL_Restart_f, "unloads GLSL shaders, they will then be reloaded as needed");
4145         Cmd_AddCommand("r_glsl_dumpshader", R_GLSL_DumpShader_f, "dumps the engine internal default.glsl shader into glsl/default.glsl");
4146         // FIXME: the client should set up r_refdef.fog stuff including the fogmasktable
4147         if (gamemode == GAME_NEHAHRA)
4148         {
4149                 Cvar_RegisterVariable (&gl_fogenable);
4150                 Cvar_RegisterVariable (&gl_fogdensity);
4151                 Cvar_RegisterVariable (&gl_fogred);
4152                 Cvar_RegisterVariable (&gl_foggreen);
4153                 Cvar_RegisterVariable (&gl_fogblue);
4154                 Cvar_RegisterVariable (&gl_fogstart);
4155                 Cvar_RegisterVariable (&gl_fogend);
4156                 Cvar_RegisterVariable (&gl_skyclip);
4157         }
4158         Cvar_RegisterVariable(&r_motionblur);
4159         Cvar_RegisterVariable(&r_damageblur);
4160         Cvar_RegisterVariable(&r_motionblur_averaging);
4161         Cvar_RegisterVariable(&r_motionblur_randomize);
4162         Cvar_RegisterVariable(&r_motionblur_minblur);
4163         Cvar_RegisterVariable(&r_motionblur_maxblur);
4164         Cvar_RegisterVariable(&r_motionblur_velocityfactor);
4165         Cvar_RegisterVariable(&r_motionblur_velocityfactor_minspeed);
4166         Cvar_RegisterVariable(&r_motionblur_velocityfactor_maxspeed);
4167         Cvar_RegisterVariable(&r_motionblur_mousefactor);
4168         Cvar_RegisterVariable(&r_motionblur_mousefactor_minspeed);
4169         Cvar_RegisterVariable(&r_motionblur_mousefactor_maxspeed);
4170         Cvar_RegisterVariable(&r_equalize_entities_fullbright);
4171         Cvar_RegisterVariable(&r_equalize_entities_minambient);
4172         Cvar_RegisterVariable(&r_equalize_entities_by);
4173         Cvar_RegisterVariable(&r_equalize_entities_to);
4174         Cvar_RegisterVariable(&r_depthfirst);
4175         Cvar_RegisterVariable(&r_useinfinitefarclip);
4176         Cvar_RegisterVariable(&r_farclip_base);
4177         Cvar_RegisterVariable(&r_farclip_world);
4178         Cvar_RegisterVariable(&r_nearclip);
4179         Cvar_RegisterVariable(&r_deformvertexes);
4180         Cvar_RegisterVariable(&r_transparent);
4181         Cvar_RegisterVariable(&r_transparent_alphatocoverage);
4182         Cvar_RegisterVariable(&r_transparent_sortsurfacesbynearest);
4183         Cvar_RegisterVariable(&r_transparent_useplanardistance);
4184         Cvar_RegisterVariable(&r_showoverdraw);
4185         Cvar_RegisterVariable(&r_showbboxes);
4186         Cvar_RegisterVariable(&r_showsurfaces);
4187         Cvar_RegisterVariable(&r_showtris);
4188         Cvar_RegisterVariable(&r_shownormals);
4189         Cvar_RegisterVariable(&r_showlighting);
4190         Cvar_RegisterVariable(&r_showshadowvolumes);
4191         Cvar_RegisterVariable(&r_showcollisionbrushes);
4192         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonfactor);
4193         Cvar_RegisterVariable(&r_showcollisionbrushes_polygonoffset);
4194         Cvar_RegisterVariable(&r_showdisabledepthtest);
4195         Cvar_RegisterVariable(&r_drawportals);
4196         Cvar_RegisterVariable(&r_drawentities);
4197         Cvar_RegisterVariable(&r_draw2d);
4198         Cvar_RegisterVariable(&r_drawworld);
4199         Cvar_RegisterVariable(&r_cullentities_trace);
4200         Cvar_RegisterVariable(&r_cullentities_trace_samples);
4201         Cvar_RegisterVariable(&r_cullentities_trace_tempentitysamples);
4202         Cvar_RegisterVariable(&r_cullentities_trace_enlarge);
4203         Cvar_RegisterVariable(&r_cullentities_trace_delay);
4204         Cvar_RegisterVariable(&r_sortentities);
4205         Cvar_RegisterVariable(&r_drawviewmodel);
4206         Cvar_RegisterVariable(&r_drawexteriormodel);
4207         Cvar_RegisterVariable(&r_speeds);
4208         Cvar_RegisterVariable(&r_fullbrights);
4209         Cvar_RegisterVariable(&r_wateralpha);
4210         Cvar_RegisterVariable(&r_dynamic);
4211         Cvar_RegisterVariable(&r_fakelight);
4212         Cvar_RegisterVariable(&r_fakelight_intensity);
4213         Cvar_RegisterVariable(&r_fullbright);
4214         Cvar_RegisterVariable(&r_shadows);
4215         Cvar_RegisterVariable(&r_shadows_darken);
4216         Cvar_RegisterVariable(&r_shadows_drawafterrtlighting);
4217         Cvar_RegisterVariable(&r_shadows_castfrombmodels);
4218         Cvar_RegisterVariable(&r_shadows_throwdistance);
4219         Cvar_RegisterVariable(&r_shadows_throwdirection);
4220         Cvar_RegisterVariable(&r_shadows_focus);
4221         Cvar_RegisterVariable(&r_shadows_shadowmapscale);
4222         Cvar_RegisterVariable(&r_q1bsp_skymasking);
4223         Cvar_RegisterVariable(&r_polygonoffset_submodel_factor);
4224         Cvar_RegisterVariable(&r_polygonoffset_submodel_offset);
4225         Cvar_RegisterVariable(&r_polygonoffset_decals_factor);
4226         Cvar_RegisterVariable(&r_polygonoffset_decals_offset);
4227         Cvar_RegisterVariable(&r_fog_exp2);
4228         Cvar_RegisterVariable(&r_fog_clear);
4229         Cvar_RegisterVariable(&r_drawfog);
4230         Cvar_RegisterVariable(&r_transparentdepthmasking);
4231         Cvar_RegisterVariable(&r_transparent_sortmindist);
4232         Cvar_RegisterVariable(&r_transparent_sortmaxdist);
4233         Cvar_RegisterVariable(&r_transparent_sortarraysize);
4234         Cvar_RegisterVariable(&r_texture_dds_load);
4235         Cvar_RegisterVariable(&r_texture_dds_save);
4236         Cvar_RegisterVariable(&r_textureunits);
4237         Cvar_RegisterVariable(&gl_combine);
4238         Cvar_RegisterVariable(&r_usedepthtextures);
4239         Cvar_RegisterVariable(&r_viewfbo);
4240         Cvar_RegisterVariable(&r_viewscale);
4241         Cvar_RegisterVariable(&r_viewscale_fpsscaling);
4242         Cvar_RegisterVariable(&r_viewscale_fpsscaling_min);
4243         Cvar_RegisterVariable(&r_viewscale_fpsscaling_multiply);
4244         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepsize);
4245         Cvar_RegisterVariable(&r_viewscale_fpsscaling_stepmax);
4246         Cvar_RegisterVariable(&r_viewscale_fpsscaling_target);
4247         Cvar_RegisterVariable(&r_glsl);
4248         Cvar_RegisterVariable(&r_glsl_deluxemapping);
4249         Cvar_RegisterVariable(&r_glsl_offsetmapping);
4250         Cvar_RegisterVariable(&r_glsl_offsetmapping_steps);
4251         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping);
4252         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_steps);
4253         Cvar_RegisterVariable(&r_glsl_offsetmapping_reliefmapping_refinesteps);
4254         Cvar_RegisterVariable(&r_glsl_offsetmapping_scale);
4255         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod);
4256         Cvar_RegisterVariable(&r_glsl_offsetmapping_lod_distance);
4257         Cvar_RegisterVariable(&r_glsl_postprocess);
4258         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1);
4259         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2);
4260         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3);
4261         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4);
4262         Cvar_RegisterVariable(&r_glsl_postprocess_uservec1_enable);
4263         Cvar_RegisterVariable(&r_glsl_postprocess_uservec2_enable);
4264         Cvar_RegisterVariable(&r_glsl_postprocess_uservec3_enable);
4265         Cvar_RegisterVariable(&r_glsl_postprocess_uservec4_enable);
4266
4267         Cvar_RegisterVariable(&r_water);
4268         Cvar_RegisterVariable(&r_water_resolutionmultiplier);
4269         Cvar_RegisterVariable(&r_water_clippingplanebias);
4270         Cvar_RegisterVariable(&r_water_refractdistort);
4271         Cvar_RegisterVariable(&r_water_reflectdistort);
4272         Cvar_RegisterVariable(&r_water_scissormode);
4273         Cvar_RegisterVariable(&r_water_lowquality);
4274         Cvar_RegisterVariable(&r_water_hideplayer);
4275         Cvar_RegisterVariable(&r_water_fbo);
4276
4277         Cvar_RegisterVariable(&r_lerpsprites);
4278         Cvar_RegisterVariable(&r_lerpmodels);
4279         Cvar_RegisterVariable(&r_lerplightstyles);
4280         Cvar_RegisterVariable(&r_waterscroll);
4281         Cvar_RegisterVariable(&r_bloom);
4282         Cvar_RegisterVariable(&r_bloom_colorscale);
4283         Cvar_RegisterVariable(&r_bloom_brighten);
4284         Cvar_RegisterVariable(&r_bloom_blur);
4285         Cvar_RegisterVariable(&r_bloom_resolution);
4286         Cvar_RegisterVariable(&r_bloom_colorexponent);
4287         Cvar_RegisterVariable(&r_bloom_colorsubtract);
4288         Cvar_RegisterVariable(&r_hdr_scenebrightness);
4289         Cvar_RegisterVariable(&r_hdr_glowintensity);
4290         Cvar_RegisterVariable(&r_hdr_irisadaptation);
4291         Cvar_RegisterVariable(&r_hdr_irisadaptation_multiplier);
4292         Cvar_RegisterVariable(&r_hdr_irisadaptation_minvalue);
4293         Cvar_RegisterVariable(&r_hdr_irisadaptation_maxvalue);
4294         Cvar_RegisterVariable(&r_hdr_irisadaptation_value);
4295         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_up);
4296         Cvar_RegisterVariable(&r_hdr_irisadaptation_fade_down);
4297         Cvar_RegisterVariable(&r_hdr_irisadaptation_radius);
4298         Cvar_RegisterVariable(&r_smoothnormals_areaweighting);
4299         Cvar_RegisterVariable(&developer_texturelogging);
4300         Cvar_RegisterVariable(&gl_lightmaps);
4301         Cvar_RegisterVariable(&r_test);
4302         Cvar_RegisterVariable(&r_glsl_saturation);
4303         Cvar_RegisterVariable(&r_glsl_saturation_redcompensate);
4304         Cvar_RegisterVariable(&r_glsl_vertextextureblend_usebothalphas);
4305         Cvar_RegisterVariable(&r_framedatasize);
4306         if (gamemode == GAME_NEHAHRA || gamemode == GAME_TENEBRAE)
4307                 Cvar_SetValue("r_fullbrights", 0);
4308         R_RegisterModule("GL_Main", gl_main_start, gl_main_shutdown, gl_main_newmap, NULL, NULL);
4309 }
4310
4311 void Render_Init(void)
4312 {
4313         gl_backend_init();
4314         R_Textures_Init();
4315         GL_Main_Init();
4316         Font_Init();
4317         GL_Draw_Init();
4318         R_Shadow_Init();
4319         R_Sky_Init();
4320         GL_Surf_Init();
4321         Sbar_Init();
4322         R_Particles_Init();
4323         R_Explosion_Init();
4324         R_LightningBeams_Init();
4325         Mod_RenderInit();
4326 }
4327
4328 /*
4329 ===============
4330 GL_Init
4331 ===============
4332 */
4333 #ifndef USE_GLES2
4334 extern char *ENGINE_EXTENSIONS;
4335 void GL_Init (void)
4336 {
4337         gl_renderer = (const char *)qglGetString(GL_RENDERER);
4338         gl_vendor = (const char *)qglGetString(GL_VENDOR);
4339         gl_version = (const char *)qglGetString(GL_VERSION);
4340         gl_extensions = (const char *)qglGetString(GL_EXTENSIONS);
4341
4342         if (!gl_extensions)
4343                 gl_extensions = "";
4344         if (!gl_platformextensions)
4345                 gl_platformextensions = "";
4346
4347         Con_Printf("GL_VENDOR: %s\n", gl_vendor);
4348         Con_Printf("GL_RENDERER: %s\n", gl_renderer);
4349         Con_Printf("GL_VERSION: %s\n", gl_version);
4350         Con_DPrintf("GL_EXTENSIONS: %s\n", gl_extensions);
4351         Con_DPrintf("%s_EXTENSIONS: %s\n", gl_platform, gl_platformextensions);
4352
4353         VID_CheckExtensions();
4354
4355         // LordHavoc: report supported extensions
4356         Con_DPrintf("\nQuakeC extensions for server and client: %s\nQuakeC extensions for menu: %s\n", vm_sv_extensions, vm_m_extensions );
4357
4358         // clear to black (loading plaque will be seen over this)
4359         GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
4360 }
4361 #endif
4362
4363 int R_CullBox(const vec3_t mins, const vec3_t maxs)
4364 {
4365         int i;
4366         mplane_t *p;
4367         if (r_trippy.integer)
4368                 return false;
4369         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
4370         {
4371                 // skip nearclip plane, it often culls portals when you are very close, and is almost never useful
4372                 if (i == 4)
4373                         continue;
4374                 p = r_refdef.view.frustum + i;
4375                 switch(p->signbits)
4376                 {
4377                 default:
4378                 case 0:
4379                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4380                                 return true;
4381                         break;
4382                 case 1:
4383                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4384                                 return true;
4385                         break;
4386                 case 2:
4387                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4388                                 return true;
4389                         break;
4390                 case 3:
4391                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4392                                 return true;
4393                         break;
4394                 case 4:
4395                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4396                                 return true;
4397                         break;
4398                 case 5:
4399                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4400                                 return true;
4401                         break;
4402                 case 6:
4403                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4404                                 return true;
4405                         break;
4406                 case 7:
4407                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4408                                 return true;
4409                         break;
4410                 }
4411         }
4412         return false;
4413 }
4414
4415 int R_CullBoxCustomPlanes(const vec3_t mins, const vec3_t maxs, int numplanes, const mplane_t *planes)
4416 {
4417         int i;
4418         const mplane_t *p;
4419         if (r_trippy.integer)
4420                 return false;
4421         for (i = 0;i < numplanes;i++)
4422         {
4423                 p = planes + i;
4424                 switch(p->signbits)
4425                 {
4426                 default:
4427                 case 0:
4428                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4429                                 return true;
4430                         break;
4431                 case 1:
4432                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*maxs[2] < p->dist)
4433                                 return true;
4434                         break;
4435                 case 2:
4436                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4437                                 return true;
4438                         break;
4439                 case 3:
4440                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*maxs[2] < p->dist)
4441                                 return true;
4442                         break;
4443                 case 4:
4444                         if (p->normal[0]*maxs[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4445                                 return true;
4446                         break;
4447                 case 5:
4448                         if (p->normal[0]*mins[0] + p->normal[1]*maxs[1] + p->normal[2]*mins[2] < p->dist)
4449                                 return true;
4450                         break;
4451                 case 6:
4452                         if (p->normal[0]*maxs[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4453                                 return true;
4454                         break;
4455                 case 7:
4456                         if (p->normal[0]*mins[0] + p->normal[1]*mins[1] + p->normal[2]*mins[2] < p->dist)
4457                                 return true;
4458                         break;
4459                 }
4460         }
4461         return false;
4462 }
4463
4464 //==================================================================================
4465
4466 // LordHavoc: this stores temporary data used within the same frame
4467
4468 typedef struct r_framedata_mem_s
4469 {
4470         struct r_framedata_mem_s *purge; // older mem block to free on next frame
4471         size_t size; // how much usable space
4472         size_t current; // how much space in use
4473         size_t mark; // last "mark" location, temporary memory can be freed by returning to this
4474         size_t wantedsize; // how much space was allocated
4475         unsigned char *data; // start of real data (16byte aligned)
4476 }
4477 r_framedata_mem_t;
4478
4479 static r_framedata_mem_t *r_framedata_mem;
4480
4481 void R_FrameData_Reset(void)
4482 {
4483         while (r_framedata_mem)
4484         {
4485                 r_framedata_mem_t *next = r_framedata_mem->purge;
4486                 Mem_Free(r_framedata_mem);
4487                 r_framedata_mem = next;
4488         }
4489 }
4490
4491 static void R_FrameData_Resize(void)
4492 {
4493         size_t wantedsize;
4494         wantedsize = (size_t)(r_framedatasize.value * 1024*1024);
4495         wantedsize = bound(65536, wantedsize, 1000*1024*1024);
4496         if (!r_framedata_mem || r_framedata_mem->wantedsize != wantedsize)
4497         {
4498                 r_framedata_mem_t *newmem = (r_framedata_mem_t *)Mem_Alloc(r_main_mempool, wantedsize);
4499                 newmem->wantedsize = wantedsize;
4500                 newmem->data = (unsigned char *)(((size_t)(newmem+1) + 15) & ~15);
4501                 newmem->size = (unsigned char *)newmem + wantedsize - newmem->data;
4502                 newmem->current = 0;
4503                 newmem->mark = 0;
4504                 newmem->purge = r_framedata_mem;
4505                 r_framedata_mem = newmem;
4506         }
4507 }
4508
4509 void R_FrameData_NewFrame(void)
4510 {
4511         R_FrameData_Resize();
4512         if (!r_framedata_mem)
4513                 return;
4514         // if we ran out of space on the last frame, free the old memory now
4515         while (r_framedata_mem->purge)
4516         {
4517                 // repeatedly remove the second item in the list, leaving only head
4518                 r_framedata_mem_t *next = r_framedata_mem->purge->purge;
4519                 Mem_Free(r_framedata_mem->purge);
4520                 r_framedata_mem->purge = next;
4521         }
4522         // reset the current mem pointer
4523         r_framedata_mem->current = 0;
4524         r_framedata_mem->mark = 0;
4525 }
4526
4527 void *R_FrameData_Alloc(size_t size)
4528 {
4529         void *data;
4530
4531         // align to 16 byte boundary - the data pointer is already aligned, so we
4532         // only need to ensure the size of every allocation is also aligned
4533         size = (size + 15) & ~15;
4534
4535         while (!r_framedata_mem || r_framedata_mem->current + size > r_framedata_mem->size)
4536         {
4537                 // emergency - we ran out of space, allocate more memory
4538                 Cvar_SetValueQuick(&r_framedatasize, bound(0.25f, r_framedatasize.value * 2.0f, 128.0f));
4539                 R_FrameData_Resize();
4540         }
4541
4542         data = r_framedata_mem->data + r_framedata_mem->current;
4543         r_framedata_mem->current += size;
4544
4545         // count the usage for stats
4546         r_refdef.stats.framedatacurrent = max(r_refdef.stats.framedatacurrent, (int)r_framedata_mem->current);
4547         r_refdef.stats.framedatasize = max(r_refdef.stats.framedatasize, (int)r_framedata_mem->size);
4548
4549         return (void *)data;
4550 }
4551
4552 void *R_FrameData_Store(size_t size, void *data)
4553 {
4554         void *d = R_FrameData_Alloc(size);
4555         if (d && data)
4556                 memcpy(d, data, size);
4557         return d;
4558 }
4559
4560 void R_FrameData_SetMark(void)
4561 {
4562         if (!r_framedata_mem)
4563                 return;
4564         r_framedata_mem->mark = r_framedata_mem->current;
4565 }
4566
4567 void R_FrameData_ReturnToMark(void)
4568 {
4569         if (!r_framedata_mem)
4570                 return;
4571         r_framedata_mem->current = r_framedata_mem->mark;
4572 }
4573
4574 //==================================================================================
4575
4576 // LordHavoc: animcache originally written by Echon, rewritten since then
4577
4578 /**
4579  * Animation cache prevents re-generating mesh data for an animated model
4580  * multiple times in one frame for lighting, shadowing, reflections, etc.
4581  */
4582
4583 void R_AnimCache_Free(void)
4584 {
4585 }
4586
4587 void R_AnimCache_ClearCache(void)
4588 {
4589         int i;
4590         entity_render_t *ent;
4591
4592         for (i = 0;i < r_refdef.scene.numentities;i++)
4593         {
4594                 ent = r_refdef.scene.entities[i];
4595                 ent->animcache_vertex3f = NULL;
4596                 ent->animcache_normal3f = NULL;
4597                 ent->animcache_svector3f = NULL;
4598                 ent->animcache_tvector3f = NULL;
4599                 ent->animcache_vertexmesh = NULL;
4600                 ent->animcache_vertex3fbuffer = NULL;
4601                 ent->animcache_vertexmeshbuffer = NULL;
4602         }
4603 }
4604
4605 static void R_AnimCache_UpdateEntityMeshBuffers(entity_render_t *ent, int numvertices)
4606 {
4607         int i;
4608
4609         // check if we need the meshbuffers
4610         if (!vid.useinterleavedarrays)
4611                 return;
4612
4613         if (!ent->animcache_vertexmesh && ent->animcache_normal3f)
4614                 ent->animcache_vertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(sizeof(r_vertexmesh_t)*numvertices);
4615         // TODO: upload vertex3f buffer?
4616         if (ent->animcache_vertexmesh)
4617         {
4618                 memcpy(ent->animcache_vertexmesh, ent->model->surfmesh.vertexmesh, sizeof(r_vertexmesh_t)*numvertices);
4619                 for (i = 0;i < numvertices;i++)
4620                         memcpy(ent->animcache_vertexmesh[i].vertex3f, ent->animcache_vertex3f + 3*i, sizeof(float[3]));
4621                 if (ent->animcache_svector3f)
4622                         for (i = 0;i < numvertices;i++)
4623                                 memcpy(ent->animcache_vertexmesh[i].svector3f, ent->animcache_svector3f + 3*i, sizeof(float[3]));
4624                 if (ent->animcache_tvector3f)
4625                         for (i = 0;i < numvertices;i++)
4626                                 memcpy(ent->animcache_vertexmesh[i].tvector3f, ent->animcache_tvector3f + 3*i, sizeof(float[3]));
4627                 if (ent->animcache_normal3f)
4628                         for (i = 0;i < numvertices;i++)
4629                                 memcpy(ent->animcache_vertexmesh[i].normal3f, ent->animcache_normal3f + 3*i, sizeof(float[3]));
4630                 // TODO: upload vertexmeshbuffer?
4631         }
4632 }
4633
4634 qboolean R_AnimCache_GetEntity(entity_render_t *ent, qboolean wantnormals, qboolean wanttangents)
4635 {
4636         dp_model_t *model = ent->model;
4637         int numvertices;
4638         // see if it's already cached this frame
4639         if (ent->animcache_vertex3f)
4640         {
4641                 // add normals/tangents if needed (this only happens with multiple views, reflections, cameras, etc)
4642                 if (wantnormals || wanttangents)
4643                 {
4644                         if (ent->animcache_normal3f)
4645                                 wantnormals = false;
4646                         if (ent->animcache_svector3f)
4647                                 wanttangents = false;
4648                         if (wantnormals || wanttangents)
4649                         {
4650                                 numvertices = model->surfmesh.num_vertices;
4651                                 if (wantnormals)
4652                                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4653                                 if (wanttangents)
4654                                 {
4655                                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4656                                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4657                                 }
4658                                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, NULL, wantnormals ? ent->animcache_normal3f : NULL, wanttangents ? ent->animcache_svector3f : NULL, wanttangents ? ent->animcache_tvector3f : NULL);
4659                                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4660                         }
4661                 }
4662         }
4663         else
4664         {
4665                 // see if this ent is worth caching
4666                 if (!model || !model->Draw || !model->surfmesh.isanimated || !model->AnimateVertices)
4667                         return false;
4668                 // get some memory for this entity and generate mesh data
4669                 numvertices = model->surfmesh.num_vertices;
4670                 ent->animcache_vertex3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4671                 if (wantnormals)
4672                         ent->animcache_normal3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4673                 if (wanttangents)
4674                 {
4675                         ent->animcache_svector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4676                         ent->animcache_tvector3f = (float *)R_FrameData_Alloc(sizeof(float[3])*numvertices);
4677                 }
4678                 model->AnimateVertices(model, ent->frameblend, ent->skeleton, ent->animcache_vertex3f, ent->animcache_normal3f, ent->animcache_svector3f, ent->animcache_tvector3f);
4679                 R_AnimCache_UpdateEntityMeshBuffers(ent, model->surfmesh.num_vertices);
4680         }
4681         return true;
4682 }
4683
4684 void R_AnimCache_CacheVisibleEntities(void)
4685 {
4686         int i;
4687         qboolean wantnormals = true;
4688         qboolean wanttangents = !r_showsurfaces.integer;
4689
4690         switch(vid.renderpath)
4691         {
4692         case RENDERPATH_GL20:
4693         case RENDERPATH_D3D9:
4694         case RENDERPATH_D3D10:
4695         case RENDERPATH_D3D11:
4696         case RENDERPATH_GLES2:
4697                 break;
4698         case RENDERPATH_GL11:
4699         case RENDERPATH_GL13:
4700         case RENDERPATH_GLES1:
4701                 wanttangents = false;
4702                 break;
4703         case RENDERPATH_SOFT:
4704                 break;
4705         }
4706
4707         if (r_shownormals.integer)
4708                 wanttangents = wantnormals = true;
4709
4710         // TODO: thread this
4711         // NOTE: R_PrepareRTLights() also caches entities
4712
4713         for (i = 0;i < r_refdef.scene.numentities;i++)
4714                 if (r_refdef.viewcache.entityvisible[i])
4715                         R_AnimCache_GetEntity(r_refdef.scene.entities[i], wantnormals, wanttangents);
4716 }
4717
4718 //==================================================================================
4719
4720 extern cvar_t r_overheadsprites_pushback;
4721
4722 static void R_View_UpdateEntityLighting (void)
4723 {
4724         int i;
4725         entity_render_t *ent;
4726         vec3_t tempdiffusenormal, avg;
4727         vec_t f, fa, fd, fdd;
4728         qboolean skipunseen = r_shadows.integer != 1; //|| R_Shadow_ShadowMappingEnabled();
4729
4730         for (i = 0;i < r_refdef.scene.numentities;i++)
4731         {
4732                 ent = r_refdef.scene.entities[i];
4733
4734                 // skip unseen models and models that updated by CSQC
4735                 if ((!r_refdef.viewcache.entityvisible[i] && skipunseen) || ent->flags & RENDER_CUSTOMIZEDMODELLIGHT)
4736                         continue;
4737
4738                 // skip bsp models
4739                 if (ent->model && (ent->model == cl.worldmodel || ent->model->brush.parentmodel == cl.worldmodel))
4740                 {
4741                         // TODO: use modellight for r_ambient settings on world?
4742                         VectorSet(ent->modellight_ambient, 0, 0, 0);
4743                         VectorSet(ent->modellight_diffuse, 0, 0, 0);
4744                         VectorSet(ent->modellight_lightdir, 0, 0, 1);
4745                         continue;
4746                 }
4747
4748                 // fetch the lighting from the worldmodel data
4749                 VectorClear(ent->modellight_ambient);
4750                 VectorClear(ent->modellight_diffuse);
4751                 VectorClear(tempdiffusenormal);
4752                 if (ent->flags & RENDER_LIGHT)
4753                 {
4754                         vec3_t org;
4755                         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
4756
4757                         // complete lightning for lit sprites
4758                         // todo: make a EF_ field so small ents could be lit purely by modellight and skipping real rtlight pass (like EF_NORTLIGHT)?
4759                         if (ent->model->type == mod_sprite && !(ent->model->data_textures[0].basematerialflags & MATERIALFLAG_FULLBRIGHT))
4760                         {
4761                                 if (ent->model->sprite.sprnum_type == SPR_OVERHEAD) // apply offset for overhead sprites
4762                                         org[2] = org[2] + r_overheadsprites_pushback.value;
4763                                 R_LightPoint(ent->modellight_ambient, org, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
4764                         }
4765                         else
4766                                 R_CompleteLightPoint(ent->modellight_ambient, ent->modellight_diffuse, tempdiffusenormal, org, LP_LIGHTMAP);
4767
4768                         if(ent->flags & RENDER_EQUALIZE)
4769                         {
4770                                 // first fix up ambient lighting...
4771                                 if(r_equalize_entities_minambient.value > 0)
4772                                 {
4773                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4774                                         if(fd > 0)
4775                                         {
4776                                                 fa = (0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2]);
4777                                                 if(fa < r_equalize_entities_minambient.value * fd)
4778                                                 {
4779                                                         // solve:
4780                                                         //   fa'/fd' = minambient
4781                                                         //   fa'+0.25*fd' = fa+0.25*fd
4782                                                         //   ...
4783                                                         //   fa' = fd' * minambient
4784                                                         //   fd'*(0.25+minambient) = fa+0.25*fd
4785                                                         //   ...
4786                                                         //   fd' = (fa+0.25*fd) * 1 / (0.25+minambient)
4787                                                         //   fa' = (fa+0.25*fd) * minambient / (0.25+minambient)
4788                                                         //   ...
4789                                                         fdd = (fa + 0.25f * fd) / (0.25f + r_equalize_entities_minambient.value);
4790                                                         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
4791                                                         VectorMA(ent->modellight_ambient, (1-f)*0.25f, ent->modellight_diffuse, ent->modellight_ambient);
4792                                                         VectorScale(ent->modellight_diffuse, f, ent->modellight_diffuse);
4793                                                 }
4794                                         }
4795                                 }
4796
4797                                 if(r_equalize_entities_to.value > 0 && r_equalize_entities_by.value != 0)
4798                                 {
4799                                         fa = 0.299f * ent->modellight_ambient[0] + 0.587f * ent->modellight_ambient[1] + 0.114f * ent->modellight_ambient[2];
4800                                         fd = 0.299f * ent->modellight_diffuse[0] + 0.587f * ent->modellight_diffuse[1] + 0.114f * ent->modellight_diffuse[2];
4801                                         f = fa + 0.25 * fd;
4802                                         if(f > 0)
4803                                         {
4804                                                 // adjust brightness and saturation to target
4805                                                 avg[0] = avg[1] = avg[2] = fa / f;
4806                                                 VectorLerp(ent->modellight_ambient, r_equalize_entities_by.value, avg, ent->modellight_ambient);
4807                                                 avg[0] = avg[1] = avg[2] = fd / f;
4808                                                 VectorLerp(ent->modellight_diffuse, r_equalize_entities_by.value, avg, ent->modellight_diffuse);
4809                                         }
4810                                 }
4811                         }
4812                 }
4813                 else // highly rare
4814                         VectorSet(ent->modellight_ambient, 1, 1, 1);
4815
4816                 // move the light direction into modelspace coordinates for lighting code
4817                 Matrix4x4_Transform3x3(&ent->inversematrix, tempdiffusenormal, ent->modellight_lightdir);
4818                 if(VectorLength2(ent->modellight_lightdir) == 0)
4819                         VectorSet(ent->modellight_lightdir, 0, 0, 1); // have to set SOME valid vector here
4820                 VectorNormalize(ent->modellight_lightdir);
4821         }
4822 }
4823
4824 #define MAX_LINEOFSIGHTTRACES 64
4825
4826 static qboolean R_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs)
4827 {
4828         int i;
4829         vec3_t boxmins, boxmaxs;
4830         vec3_t start;
4831         vec3_t end;
4832         dp_model_t *model = r_refdef.scene.worldmodel;
4833
4834         if (!model || !model->brush.TraceLineOfSight)
4835                 return true;
4836
4837         // expand the box a little
4838         boxmins[0] = (enlarge+1) * entboxmins[0] - enlarge * entboxmaxs[0];
4839         boxmaxs[0] = (enlarge+1) * entboxmaxs[0] - enlarge * entboxmins[0];
4840         boxmins[1] = (enlarge+1) * entboxmins[1] - enlarge * entboxmaxs[1];
4841         boxmaxs[1] = (enlarge+1) * entboxmaxs[1] - enlarge * entboxmins[1];
4842         boxmins[2] = (enlarge+1) * entboxmins[2] - enlarge * entboxmaxs[2];
4843         boxmaxs[2] = (enlarge+1) * entboxmaxs[2] - enlarge * entboxmins[2];
4844
4845         // return true if eye is inside enlarged box
4846         if (BoxesOverlap(boxmins, boxmaxs, eye, eye))
4847                 return true;
4848
4849         // try center
4850         VectorCopy(eye, start);
4851         VectorMAM(0.5f, boxmins, 0.5f, boxmaxs, end);
4852         if (model->brush.TraceLineOfSight(model, start, end))
4853                 return true;
4854
4855         // try various random positions
4856         for (i = 0;i < numsamples;i++)
4857         {
4858                 VectorSet(end, lhrandom(boxmins[0], boxmaxs[0]), lhrandom(boxmins[1], boxmaxs[1]), lhrandom(boxmins[2], boxmaxs[2]));
4859                 if (model->brush.TraceLineOfSight(model, start, end))
4860                         return true;
4861         }
4862
4863         return false;
4864 }
4865
4866
4867 static void R_View_UpdateEntityVisible (void)
4868 {
4869         int i;
4870         int renderimask;
4871         int samples;
4872         entity_render_t *ent;
4873
4874         renderimask = r_refdef.envmap                                    ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4875                 : r_fb.water.hideplayer                                      ? (RENDER_EXTERIORMODEL | RENDER_VIEWMODEL)
4876                 : (chase_active.integer || r_fb.water.renderingscene)  ? RENDER_VIEWMODEL
4877                 :                                                          RENDER_EXTERIORMODEL;
4878         if (!r_drawviewmodel.integer)
4879                 renderimask |= RENDER_VIEWMODEL;
4880         if (!r_drawexteriormodel.integer)
4881                 renderimask |= RENDER_EXTERIORMODEL;
4882         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.BoxTouchingVisibleLeafs)
4883         {
4884                 // worldmodel can check visibility
4885                 memset(r_refdef.viewcache.entityvisible, 0, r_refdef.scene.numentities);
4886                 for (i = 0;i < r_refdef.scene.numentities;i++)
4887                 {
4888                         ent = r_refdef.scene.entities[i];
4889                         if (!(ent->flags & renderimask))
4890                         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)))
4891                         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))
4892                                 r_refdef.viewcache.entityvisible[i] = true;
4893                 }
4894         }
4895         else
4896         {
4897                 // no worldmodel or it can't check visibility
4898                 for (i = 0;i < r_refdef.scene.numentities;i++)
4899                 {
4900                         ent = r_refdef.scene.entities[i];
4901                         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));
4902                 }
4903         }
4904         if(r_cullentities_trace.integer && r_refdef.scene.worldmodel->brush.TraceLineOfSight && !r_refdef.view.useclipplane && !r_trippy.integer)
4905                 // sorry, this check doesn't work for portal/reflection/refraction renders as the view origin is not useful for culling
4906         {
4907                 for (i = 0;i < r_refdef.scene.numentities;i++)
4908                 {
4909                         if (!r_refdef.viewcache.entityvisible[i])
4910                                 continue;
4911                         ent = r_refdef.scene.entities[i];
4912                         if(!(ent->flags & (RENDER_VIEWMODEL | RENDER_WORLDOBJECT | RENDER_NODEPTHTEST)) && !(ent->model && (ent->model->name[0] == '*')))
4913                         {
4914                                 samples = ent->entitynumber ? r_cullentities_trace_samples.integer : r_cullentities_trace_tempentitysamples.integer;
4915                                 if (samples < 0)
4916                                         continue; // temp entities do pvs only
4917                                 if(R_CanSeeBox(samples, r_cullentities_trace_enlarge.value, r_refdef.view.origin, ent->mins, ent->maxs))
4918                                         ent->last_trace_visibility = realtime;
4919                                 if(ent->last_trace_visibility < realtime - r_cullentities_trace_delay.value)
4920                                         r_refdef.viewcache.entityvisible[i] = 0;
4921                         }
4922                 }
4923         }
4924 }
4925
4926 /// only used if skyrendermasked, and normally returns false
4927 static int R_DrawBrushModelsSky (void)
4928 {
4929         int i, sky;
4930         entity_render_t *ent;
4931
4932         sky = false;
4933         for (i = 0;i < r_refdef.scene.numentities;i++)
4934         {
4935                 if (!r_refdef.viewcache.entityvisible[i])
4936                         continue;
4937                 ent = r_refdef.scene.entities[i];
4938                 if (!ent->model || !ent->model->DrawSky)
4939                         continue;
4940                 ent->model->DrawSky(ent);
4941                 sky = true;
4942         }
4943         return sky;
4944 }
4945
4946 static void R_DrawNoModel(entity_render_t *ent);
4947 static void R_DrawModels(void)
4948 {
4949         int i;
4950         entity_render_t *ent;
4951
4952         for (i = 0;i < r_refdef.scene.numentities;i++)
4953         {
4954                 if (!r_refdef.viewcache.entityvisible[i])
4955                         continue;
4956                 ent = r_refdef.scene.entities[i];
4957                 r_refdef.stats.entities++;
4958                 /*
4959                 if (ent->model && !strncmp(ent->model->name, "models/proto_", 13))
4960                 {
4961                         vec3_t f, l, u, o;
4962                         Matrix4x4_ToVectors(&ent->matrix, f, l, u, o);
4963                         Con_Printf("R_DrawModels\n");
4964                         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]);
4965                         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);
4966                         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);
4967                 }
4968                 */
4969                 if (ent->model && ent->model->Draw != NULL)
4970                         ent->model->Draw(ent);
4971                 else
4972                         R_DrawNoModel(ent);
4973         }
4974 }
4975
4976 static void R_DrawModelsDepth(void)
4977 {
4978         int i;
4979         entity_render_t *ent;
4980
4981         for (i = 0;i < r_refdef.scene.numentities;i++)
4982         {
4983                 if (!r_refdef.viewcache.entityvisible[i])
4984                         continue;
4985                 ent = r_refdef.scene.entities[i];
4986                 if (ent->model && ent->model->DrawDepth != NULL)
4987                         ent->model->DrawDepth(ent);
4988         }
4989 }
4990
4991 static void R_DrawModelsDebug(void)
4992 {
4993         int i;
4994         entity_render_t *ent;
4995
4996         for (i = 0;i < r_refdef.scene.numentities;i++)
4997         {
4998                 if (!r_refdef.viewcache.entityvisible[i])
4999                         continue;
5000                 ent = r_refdef.scene.entities[i];
5001                 if (ent->model && ent->model->DrawDebug != NULL)
5002                         ent->model->DrawDebug(ent);
5003         }
5004 }
5005
5006 static void R_DrawModelsAddWaterPlanes(void)
5007 {
5008         int i;
5009         entity_render_t *ent;
5010
5011         for (i = 0;i < r_refdef.scene.numentities;i++)
5012         {
5013                 if (!r_refdef.viewcache.entityvisible[i])
5014                         continue;
5015                 ent = r_refdef.scene.entities[i];
5016                 if (ent->model && ent->model->DrawAddWaterPlanes != NULL)
5017                         ent->model->DrawAddWaterPlanes(ent);
5018         }
5019 }
5020
5021 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}};
5022
5023 void R_HDR_UpdateIrisAdaptation(const vec3_t point)
5024 {
5025         if (r_hdr_irisadaptation.integer)
5026         {
5027                 vec3_t p;
5028                 vec3_t ambient;
5029                 vec3_t diffuse;
5030                 vec3_t diffusenormal;
5031                 vec3_t forward;
5032                 vec_t brightness = 0.0f;
5033                 vec_t goal;
5034                 vec_t current;
5035                 vec_t d;
5036                 int c;
5037                 VectorCopy(r_refdef.view.forward, forward);
5038                 for (c = 0;c < (int)(sizeof(irisvecs)/sizeof(irisvecs[0]));c++)
5039                 {
5040                         p[0] = point[0] + irisvecs[c][0] * r_hdr_irisadaptation_radius.value;
5041                         p[1] = point[1] + irisvecs[c][1] * r_hdr_irisadaptation_radius.value;
5042                         p[2] = point[2] + irisvecs[c][2] * r_hdr_irisadaptation_radius.value;
5043                         R_CompleteLightPoint(ambient, diffuse, diffusenormal, p, LP_LIGHTMAP | LP_RTWORLD | LP_DYNLIGHT);
5044                         d = DotProduct(forward, diffusenormal);
5045                         brightness += VectorLength(ambient);
5046                         if (d > 0)
5047                                 brightness += d * VectorLength(diffuse);
5048                 }
5049                 brightness *= 1.0f / c;
5050                 brightness += 0.00001f; // make sure it's never zero
5051                 goal = r_hdr_irisadaptation_multiplier.value / brightness;
5052                 goal = bound(r_hdr_irisadaptation_minvalue.value, goal, r_hdr_irisadaptation_maxvalue.value);
5053                 current = r_hdr_irisadaptation_value.value;
5054                 if (current < goal)
5055                         current = min(current + r_hdr_irisadaptation_fade_up.value * cl.realframetime, goal);
5056                 else if (current > goal)
5057                         current = max(current - r_hdr_irisadaptation_fade_down.value * cl.realframetime, goal);
5058                 if (fabs(r_hdr_irisadaptation_value.value - current) > 0.0001f)
5059                         Cvar_SetValueQuick(&r_hdr_irisadaptation_value, current);
5060         }
5061         else if (r_hdr_irisadaptation_value.value != 1.0f)
5062                 Cvar_SetValueQuick(&r_hdr_irisadaptation_value, 1.0f);
5063 }
5064
5065 static void R_View_SetFrustum(const int *scissor)
5066 {
5067         int i;
5068         double fpx = +1, fnx = -1, fpy = +1, fny = -1;
5069         vec3_t forward, left, up, origin, v;
5070
5071         if(scissor)
5072         {
5073                 // flipped x coordinates (because x points left here)
5074                 fpx =  1.0 - 2.0 * (scissor[0]              - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5075                 fnx =  1.0 - 2.0 * (scissor[0] + scissor[2] - r_refdef.view.viewport.x) / (double) (r_refdef.view.viewport.width);
5076
5077                 // D3D Y coordinate is top to bottom, OpenGL is bottom to top, fix the D3D one
5078                 switch(vid.renderpath)
5079                 {
5080                         case RENDERPATH_D3D9:
5081                         case RENDERPATH_D3D10:
5082                         case RENDERPATH_D3D11:
5083                                 // non-flipped y coordinates
5084                                 fny = -1.0 + 2.0 * (vid.height - scissor[1] - scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5085                                 fpy = -1.0 + 2.0 * (vid.height - scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5086                                 break;
5087                         case RENDERPATH_SOFT:
5088                         case RENDERPATH_GL11:
5089                         case RENDERPATH_GL13:
5090                         case RENDERPATH_GL20:
5091                         case RENDERPATH_GLES1:
5092                         case RENDERPATH_GLES2:
5093                                 // non-flipped y coordinates
5094                                 fny = -1.0 + 2.0 * (scissor[1]              - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5095                                 fpy = -1.0 + 2.0 * (scissor[1] + scissor[3] - r_refdef.view.viewport.y) / (double) (r_refdef.view.viewport.height);
5096                                 break;
5097                 }
5098         }
5099
5100         // we can't trust r_refdef.view.forward and friends in reflected scenes
5101         Matrix4x4_ToVectors(&r_refdef.view.matrix, forward, left, up, origin);
5102
5103 #if 0
5104         r_refdef.view.frustum[0].normal[0] = 0 - 1.0 / r_refdef.view.frustum_x;
5105         r_refdef.view.frustum[0].normal[1] = 0 - 0;
5106         r_refdef.view.frustum[0].normal[2] = -1 - 0;
5107         r_refdef.view.frustum[1].normal[0] = 0 + 1.0 / r_refdef.view.frustum_x;
5108         r_refdef.view.frustum[1].normal[1] = 0 + 0;
5109         r_refdef.view.frustum[1].normal[2] = -1 + 0;
5110         r_refdef.view.frustum[2].normal[0] = 0 - 0;
5111         r_refdef.view.frustum[2].normal[1] = 0 - 1.0 / r_refdef.view.frustum_y;
5112         r_refdef.view.frustum[2].normal[2] = -1 - 0;
5113         r_refdef.view.frustum[3].normal[0] = 0 + 0;
5114         r_refdef.view.frustum[3].normal[1] = 0 + 1.0 / r_refdef.view.frustum_y;
5115         r_refdef.view.frustum[3].normal[2] = -1 + 0;
5116 #endif
5117
5118 #if 0
5119         zNear = r_refdef.nearclip;
5120         nudge = 1.0 - 1.0 / (1<<23);
5121         r_refdef.view.frustum[4].normal[0] = 0 - 0;
5122         r_refdef.view.frustum[4].normal[1] = 0 - 0;
5123         r_refdef.view.frustum[4].normal[2] = -1 - -nudge;
5124         r_refdef.view.frustum[4].dist = 0 - -2 * zNear * nudge;
5125         r_refdef.view.frustum[5].normal[0] = 0 + 0;
5126         r_refdef.view.frustum[5].normal[1] = 0 + 0;
5127         r_refdef.view.frustum[5].normal[2] = -1 + -nudge;
5128         r_refdef.view.frustum[5].dist = 0 + -2 * zNear * nudge;
5129 #endif
5130
5131
5132
5133 #if 0
5134         r_refdef.view.frustum[0].normal[0] = m[3] - m[0];
5135         r_refdef.view.frustum[0].normal[1] = m[7] - m[4];
5136         r_refdef.view.frustum[0].normal[2] = m[11] - m[8];
5137         r_refdef.view.frustum[0].dist = m[15] - m[12];
5138
5139         r_refdef.view.frustum[1].normal[0] = m[3] + m[0];
5140         r_refdef.view.frustum[1].normal[1] = m[7] + m[4];
5141         r_refdef.view.frustum[1].normal[2] = m[11] + m[8];
5142         r_refdef.view.frustum[1].dist = m[15] + m[12];
5143
5144         r_refdef.view.frustum[2].normal[0] = m[3] - m[1];
5145         r_refdef.view.frustum[2].normal[1] = m[7] - m[5];
5146         r_refdef.view.frustum[2].normal[2] = m[11] - m[9];
5147         r_refdef.view.frustum[2].dist = m[15] - m[13];
5148
5149         r_refdef.view.frustum[3].normal[0] = m[3] + m[1];
5150         r_refdef.view.frustum[3].normal[1] = m[7] + m[5];
5151         r_refdef.view.frustum[3].normal[2] = m[11] + m[9];
5152         r_refdef.view.frustum[3].dist = m[15] + m[13];
5153
5154         r_refdef.view.frustum[4].normal[0] = m[3] - m[2];
5155         r_refdef.view.frustum[4].normal[1] = m[7] - m[6];
5156         r_refdef.view.frustum[4].normal[2] = m[11] - m[10];
5157         r_refdef.view.frustum[4].dist = m[15] - m[14];
5158
5159         r_refdef.view.frustum[5].normal[0] = m[3] + m[2];
5160         r_refdef.view.frustum[5].normal[1] = m[7] + m[6];
5161         r_refdef.view.frustum[5].normal[2] = m[11] + m[10];
5162         r_refdef.view.frustum[5].dist = m[15] + m[14];
5163 #endif
5164
5165         if (r_refdef.view.useperspective)
5166         {
5167                 // calculate frustum corners, which are used to calculate deformed frustum planes for shadow caster culling
5168                 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]);
5169                 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]);
5170                 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]);
5171                 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]);
5172
5173                 // then the normals from the corners relative to origin
5174                 CrossProduct(r_refdef.view.frustumcorner[2], r_refdef.view.frustumcorner[0], r_refdef.view.frustum[0].normal);
5175                 CrossProduct(r_refdef.view.frustumcorner[1], r_refdef.view.frustumcorner[3], r_refdef.view.frustum[1].normal);
5176                 CrossProduct(r_refdef.view.frustumcorner[0], r_refdef.view.frustumcorner[1], r_refdef.view.frustum[2].normal);
5177                 CrossProduct(r_refdef.view.frustumcorner[3], r_refdef.view.frustumcorner[2], r_refdef.view.frustum[3].normal);
5178
5179                 // in a NORMAL view, forward cross left == up
5180                 // in a REFLECTED view, forward cross left == down
5181                 // so our cross products above need to be adjusted for a left handed coordinate system
5182                 CrossProduct(forward, left, v);
5183                 if(DotProduct(v, up) < 0)
5184                 {
5185                         VectorNegate(r_refdef.view.frustum[0].normal, r_refdef.view.frustum[0].normal);
5186                         VectorNegate(r_refdef.view.frustum[1].normal, r_refdef.view.frustum[1].normal);
5187                         VectorNegate(r_refdef.view.frustum[2].normal, r_refdef.view.frustum[2].normal);
5188                         VectorNegate(r_refdef.view.frustum[3].normal, r_refdef.view.frustum[3].normal);
5189                 }
5190
5191                 // Leaving those out was a mistake, those were in the old code, and they
5192                 // fix a reproducable bug in this one: frustum culling got fucked up when viewmatrix was an identity matrix
5193                 // I couldn't reproduce it after adding those normalizations. --blub
5194                 VectorNormalize(r_refdef.view.frustum[0].normal);
5195                 VectorNormalize(r_refdef.view.frustum[1].normal);
5196                 VectorNormalize(r_refdef.view.frustum[2].normal);
5197                 VectorNormalize(r_refdef.view.frustum[3].normal);
5198
5199                 // make the corners absolute
5200                 VectorAdd(r_refdef.view.frustumcorner[0], r_refdef.view.origin, r_refdef.view.frustumcorner[0]);
5201                 VectorAdd(r_refdef.view.frustumcorner[1], r_refdef.view.origin, r_refdef.view.frustumcorner[1]);
5202                 VectorAdd(r_refdef.view.frustumcorner[2], r_refdef.view.origin, r_refdef.view.frustumcorner[2]);
5203                 VectorAdd(r_refdef.view.frustumcorner[3], r_refdef.view.origin, r_refdef.view.frustumcorner[3]);
5204
5205                 // one more normal
5206                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5207
5208                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal);
5209                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal);
5210                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal);
5211                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal);
5212                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5213         }
5214         else
5215         {
5216                 VectorScale(left, -r_refdef.view.ortho_x, r_refdef.view.frustum[0].normal);
5217                 VectorScale(left,  r_refdef.view.ortho_x, r_refdef.view.frustum[1].normal);
5218                 VectorScale(up, -r_refdef.view.ortho_y, r_refdef.view.frustum[2].normal);
5219                 VectorScale(up,  r_refdef.view.ortho_y, r_refdef.view.frustum[3].normal);
5220                 VectorCopy(forward, r_refdef.view.frustum[4].normal);
5221                 r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[0].normal) + r_refdef.view.ortho_x;
5222                 r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[1].normal) + r_refdef.view.ortho_x;
5223                 r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[2].normal) + r_refdef.view.ortho_y;
5224                 r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[3].normal) + r_refdef.view.ortho_y;
5225                 r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, r_refdef.view.frustum[4].normal) + r_refdef.nearclip;
5226         }
5227         r_refdef.view.numfrustumplanes = 5;
5228
5229         if (r_refdef.view.useclipplane)
5230         {
5231                 r_refdef.view.numfrustumplanes = 6;
5232                 r_refdef.view.frustum[5] = r_refdef.view.clipplane;
5233         }
5234
5235         for (i = 0;i < r_refdef.view.numfrustumplanes;i++)
5236                 PlaneClassify(r_refdef.view.frustum + i);
5237
5238         // LordHavoc: note to all quake engine coders, Quake had a special case
5239         // for 90 degrees which assumed a square view (wrong), so I removed it,
5240         // Quake2 has it disabled as well.
5241
5242         // rotate R_VIEWFORWARD right by FOV_X/2 degrees
5243         //RotatePointAroundVector( r_refdef.view.frustum[0].normal, up, forward, -(90 - r_refdef.fov_x / 2));
5244         //r_refdef.view.frustum[0].dist = DotProduct (r_refdef.view.origin, frustum[0].normal);
5245         //PlaneClassify(&frustum[0]);
5246
5247         // rotate R_VIEWFORWARD left by FOV_X/2 degrees
5248         //RotatePointAroundVector( r_refdef.view.frustum[1].normal, up, forward, (90 - r_refdef.fov_x / 2));
5249         //r_refdef.view.frustum[1].dist = DotProduct (r_refdef.view.origin, frustum[1].normal);
5250         //PlaneClassify(&frustum[1]);
5251
5252         // rotate R_VIEWFORWARD up by FOV_X/2 degrees
5253         //RotatePointAroundVector( r_refdef.view.frustum[2].normal, left, forward, -(90 - r_refdef.fov_y / 2));
5254         //r_refdef.view.frustum[2].dist = DotProduct (r_refdef.view.origin, frustum[2].normal);
5255         //PlaneClassify(&frustum[2]);
5256
5257         // rotate R_VIEWFORWARD down by FOV_X/2 degrees
5258         //RotatePointAroundVector( r_refdef.view.frustum[3].normal, left, forward, (90 - r_refdef.fov_y / 2));
5259         //r_refdef.view.frustum[3].dist = DotProduct (r_refdef.view.origin, frustum[3].normal);
5260         //PlaneClassify(&frustum[3]);
5261
5262         // nearclip plane
5263         //VectorCopy(forward, r_refdef.view.frustum[4].normal);
5264         //r_refdef.view.frustum[4].dist = DotProduct (r_refdef.view.origin, frustum[4].normal) + r_nearclip.value;
5265         //PlaneClassify(&frustum[4]);
5266 }
5267
5268 static void R_View_UpdateWithScissor(const int *myscissor)
5269 {
5270         R_Main_ResizeViewCache();
5271         R_View_SetFrustum(myscissor);
5272         R_View_WorldVisibility(r_refdef.view.useclipplane);
5273         R_View_UpdateEntityVisible();
5274         R_View_UpdateEntityLighting();
5275         R_AnimCache_CacheVisibleEntities();
5276 }
5277
5278 static void R_View_Update(void)
5279 {
5280         R_Main_ResizeViewCache();
5281         R_View_SetFrustum(NULL);
5282         R_View_WorldVisibility(r_refdef.view.useclipplane);
5283         R_View_UpdateEntityVisible();
5284         R_View_UpdateEntityLighting();
5285         R_AnimCache_CacheVisibleEntities();
5286 }
5287
5288 float viewscalefpsadjusted = 1.0f;
5289
5290 static void R_GetScaledViewSize(int width, int height, int *outwidth, int *outheight)
5291 {
5292         float scale = r_viewscale.value * sqrt(viewscalefpsadjusted);
5293         scale = bound(0.03125f, scale, 1.0f);
5294         *outwidth = (int)ceil(width * scale);
5295         *outheight = (int)ceil(height * scale);
5296 }
5297
5298 void R_SetupView(qboolean allowwaterclippingplane, int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5299 {
5300         const float *customclipplane = NULL;
5301         float plane[4];
5302         int /*rtwidth,*/ rtheight, scaledwidth, scaledheight;
5303         if (r_refdef.view.useclipplane && allowwaterclippingplane)
5304         {
5305                 // LordHavoc: couldn't figure out how to make this approach the
5306                 vec_t dist = r_refdef.view.clipplane.dist - r_water_clippingplanebias.value;
5307                 vec_t viewdist = DotProduct(r_refdef.view.origin, r_refdef.view.clipplane.normal);
5308                 if (viewdist < r_refdef.view.clipplane.dist + r_water_clippingplanebias.value)
5309                         dist = r_refdef.view.clipplane.dist;
5310                 plane[0] = r_refdef.view.clipplane.normal[0];
5311                 plane[1] = r_refdef.view.clipplane.normal[1];
5312                 plane[2] = r_refdef.view.clipplane.normal[2];
5313                 plane[3] = -dist;
5314                 if(vid.renderpath != RENDERPATH_SOFT) customclipplane = plane;
5315         }
5316
5317         //rtwidth = fbo ? R_TextureWidth(depthtexture ? depthtexture : colortexture) : vid.width;
5318         rtheight = fbo ? R_TextureHeight(depthtexture ? depthtexture : colortexture) : vid.height;
5319
5320         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &scaledwidth, &scaledheight);
5321         if (!r_refdef.view.useperspective)
5322                 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);
5323         else if (vid.stencil && r_useinfinitefarclip.integer)
5324                 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);
5325         else
5326                 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);
5327         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5328         R_SetViewport(&r_refdef.view.viewport);
5329         if (r_refdef.view.useclipplane && allowwaterclippingplane && vid.renderpath == RENDERPATH_SOFT)
5330         {
5331                 matrix4x4_t mvpmatrix, invmvpmatrix, invtransmvpmatrix;
5332                 float screenplane[4];
5333                 Matrix4x4_Concat(&mvpmatrix, &r_refdef.view.viewport.projectmatrix, &r_refdef.view.viewport.viewmatrix);
5334                 Matrix4x4_Invert_Full(&invmvpmatrix, &mvpmatrix);
5335                 Matrix4x4_Transpose(&invtransmvpmatrix, &invmvpmatrix);
5336                 Matrix4x4_Transform4(&invtransmvpmatrix, plane, screenplane);
5337                 DPSOFTRAST_ClipPlane(screenplane[0], screenplane[1], screenplane[2], screenplane[3]);
5338         }
5339 }
5340
5341 void R_EntityMatrix(const matrix4x4_t *matrix)
5342 {
5343         if (gl_modelmatrixchanged || memcmp(matrix, &gl_modelmatrix, sizeof(matrix4x4_t)))
5344         {
5345                 gl_modelmatrixchanged = false;
5346                 gl_modelmatrix = *matrix;
5347                 Matrix4x4_Concat(&gl_modelviewmatrix, &gl_viewmatrix, &gl_modelmatrix);
5348                 Matrix4x4_Concat(&gl_modelviewprojectionmatrix, &gl_projectionmatrix, &gl_modelviewmatrix);
5349                 Matrix4x4_ToArrayFloatGL(&gl_modelviewmatrix, gl_modelview16f);
5350                 Matrix4x4_ToArrayFloatGL(&gl_modelviewprojectionmatrix, gl_modelviewprojection16f);
5351                 CHECKGLERROR
5352                 switch(vid.renderpath)
5353                 {
5354                 case RENDERPATH_D3D9:
5355 #ifdef SUPPORTD3D
5356                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewProjectionMatrix, gl_modelviewprojection16f);
5357                         hlslVSSetParameter16f(D3DVSREGISTER_ModelViewMatrix, gl_modelview16f);
5358 #endif
5359                         break;
5360                 case RENDERPATH_D3D10:
5361                         Con_DPrintf("FIXME D3D10 shader %s:%i\n", __FILE__, __LINE__);
5362                         break;
5363                 case RENDERPATH_D3D11:
5364                         Con_DPrintf("FIXME D3D11 shader %s:%i\n", __FILE__, __LINE__);
5365                         break;
5366                 case RENDERPATH_GL11:
5367                 case RENDERPATH_GL13:
5368                 case RENDERPATH_GLES1:
5369                         qglLoadMatrixf(gl_modelview16f);CHECKGLERROR
5370                         break;
5371                 case RENDERPATH_SOFT:
5372                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewProjectionMatrixM1, 1, false, gl_modelviewprojection16f);
5373                         DPSOFTRAST_UniformMatrix4fv(DPSOFTRAST_UNIFORM_ModelViewMatrixM1, 1, false, gl_modelview16f);
5374                         break;
5375                 case RENDERPATH_GL20:
5376                 case RENDERPATH_GLES2:
5377                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewProjectionMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewProjectionMatrix, 1, false, gl_modelviewprojection16f);
5378                         if (r_glsl_permutation && r_glsl_permutation->loc_ModelViewMatrix >= 0) qglUniformMatrix4fv(r_glsl_permutation->loc_ModelViewMatrix, 1, false, gl_modelview16f);
5379                         break;
5380                 }
5381         }
5382 }
5383
5384 void R_ResetViewRendering2D_Common(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, float x2, float y2)
5385 {
5386         r_viewport_t viewport;
5387
5388         CHECKGLERROR
5389
5390         // GL is weird because it's bottom to top, r_refdef.view.y is top to bottom
5391         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);
5392         R_Mesh_SetRenderTargets(fbo, depthtexture, colortexture, NULL, NULL, NULL);
5393         R_SetViewport(&viewport);
5394         GL_Scissor(viewport.x, viewport.y, viewport.width, viewport.height);
5395         GL_Color(1, 1, 1, 1);
5396         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5397         GL_BlendFunc(GL_ONE, GL_ZERO);
5398         GL_ScissorTest(false);
5399         GL_DepthMask(false);
5400         GL_DepthRange(0, 1);
5401         GL_DepthTest(false);
5402         GL_DepthFunc(GL_LEQUAL);
5403         R_EntityMatrix(&identitymatrix);
5404         R_Mesh_ResetTextureState();
5405         GL_PolygonOffset(0, 0);
5406         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5407         switch(vid.renderpath)
5408         {
5409         case RENDERPATH_GL11:
5410         case RENDERPATH_GL13:
5411         case RENDERPATH_GL20:
5412         case RENDERPATH_GLES1:
5413         case RENDERPATH_GLES2:
5414                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5415                 break;
5416         case RENDERPATH_D3D9:
5417         case RENDERPATH_D3D10:
5418         case RENDERPATH_D3D11:
5419         case RENDERPATH_SOFT:
5420                 break;
5421         }
5422         GL_CullFace(GL_NONE);
5423
5424         CHECKGLERROR
5425 }
5426
5427 void R_ResetViewRendering2D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5428 {
5429         DrawQ_Finish();
5430
5431         R_ResetViewRendering2D_Common(fbo, depthtexture, colortexture, 1, 1);
5432 }
5433
5434 void R_ResetViewRendering3D(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5435 {
5436         DrawQ_Finish();
5437
5438         R_SetupView(true, fbo, depthtexture, colortexture);
5439         GL_Scissor(r_refdef.view.viewport.x, r_refdef.view.viewport.y, r_refdef.view.viewport.width, r_refdef.view.viewport.height);
5440         GL_Color(1, 1, 1, 1);
5441         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
5442         GL_BlendFunc(GL_ONE, GL_ZERO);
5443         GL_ScissorTest(true);
5444         GL_DepthMask(true);
5445         GL_DepthRange(0, 1);
5446         GL_DepthTest(true);
5447         GL_DepthFunc(GL_LEQUAL);
5448         R_EntityMatrix(&identitymatrix);
5449         R_Mesh_ResetTextureState();
5450         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
5451         R_SetStencil(false, 255, GL_KEEP, GL_KEEP, GL_KEEP, GL_ALWAYS, 128, 255);
5452         switch(vid.renderpath)
5453         {
5454         case RENDERPATH_GL11:
5455         case RENDERPATH_GL13:
5456         case RENDERPATH_GL20:
5457         case RENDERPATH_GLES1:
5458         case RENDERPATH_GLES2:
5459                 qglEnable(GL_POLYGON_OFFSET_FILL);CHECKGLERROR
5460                 break;
5461         case RENDERPATH_D3D9:
5462         case RENDERPATH_D3D10:
5463         case RENDERPATH_D3D11:
5464         case RENDERPATH_SOFT:
5465                 break;
5466         }
5467         GL_CullFace(r_refdef.view.cullface_back);
5468 }
5469
5470 /*
5471 ================
5472 R_RenderView_UpdateViewVectors
5473 ================
5474 */
5475 void R_RenderView_UpdateViewVectors(void)
5476 {
5477         // break apart the view matrix into vectors for various purposes
5478         // it is important that this occurs outside the RenderScene function because that can be called from reflection renders, where the vectors come out wrong
5479         // however the r_refdef.view.origin IS updated in RenderScene intentionally - otherwise the sky renders at the wrong origin, etc
5480         Matrix4x4_ToVectors(&r_refdef.view.matrix, r_refdef.view.forward, r_refdef.view.left, r_refdef.view.up, r_refdef.view.origin);
5481         VectorNegate(r_refdef.view.left, r_refdef.view.right);
5482         // make an inverted copy of the view matrix for tracking sprites
5483         Matrix4x4_Invert_Simple(&r_refdef.view.inverse_matrix, &r_refdef.view.matrix);
5484 }
5485
5486 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5487 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture);
5488
5489 static void R_Water_StartFrame(void)
5490 {
5491         int i;
5492         int waterwidth, waterheight, texturewidth, textureheight, camerawidth, cameraheight;
5493         r_waterstate_waterplane_t *p;
5494         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5495
5496         if (vid.width > (int)vid.maxtexturesize_2d || vid.height > (int)vid.maxtexturesize_2d)
5497                 return;
5498
5499         switch(vid.renderpath)
5500         {
5501         case RENDERPATH_GL20:
5502         case RENDERPATH_D3D9:
5503         case RENDERPATH_D3D10:
5504         case RENDERPATH_D3D11:
5505         case RENDERPATH_SOFT:
5506         case RENDERPATH_GLES2:
5507                 break;
5508         case RENDERPATH_GL11:
5509         case RENDERPATH_GL13:
5510         case RENDERPATH_GLES1:
5511                 return;
5512         }
5513
5514         // set waterwidth and waterheight to the water resolution that will be
5515         // used (often less than the screen resolution for faster rendering)
5516         R_GetScaledViewSize(bound(1, vid.width * r_water_resolutionmultiplier.value, vid.width), bound(1, vid.height * r_water_resolutionmultiplier.value, vid.height), &waterwidth, &waterheight);
5517
5518         // calculate desired texture sizes
5519         // can't use water if the card does not support the texture size
5520         if (!r_water.integer || r_showsurfaces.integer)
5521                 texturewidth = textureheight = waterwidth = waterheight = camerawidth = cameraheight = 0;
5522         else if (vid.support.arb_texture_non_power_of_two)
5523         {
5524                 texturewidth = waterwidth;
5525                 textureheight = waterheight;
5526                 camerawidth = waterwidth;
5527                 cameraheight = waterheight;
5528         }
5529         else
5530         {
5531                 for (texturewidth   = 1;texturewidth   < waterwidth ;texturewidth   *= 2);
5532                 for (textureheight  = 1;textureheight  < waterheight;textureheight  *= 2);
5533                 for (camerawidth    = 1;camerawidth   <= waterwidth; camerawidth    *= 2); camerawidth  /= 2;
5534                 for (cameraheight   = 1;cameraheight  <= waterheight;cameraheight   *= 2); cameraheight /= 2;
5535         }
5536
5537         // allocate textures as needed
5538         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))
5539         {
5540                 r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5541                 for (i = 0, p = r_fb.water.waterplanes;i < r_fb.water.maxwaterplanes;i++, p++)
5542                 {
5543                         if (p->texture_refraction)
5544                                 R_FreeTexture(p->texture_refraction);
5545                         p->texture_refraction = NULL;
5546                         if (p->fbo_refraction)
5547                                 R_Mesh_DestroyFramebufferObject(p->fbo_refraction);
5548                         p->fbo_refraction = 0;
5549                         if (p->texture_reflection)
5550                                 R_FreeTexture(p->texture_reflection);
5551                         p->texture_reflection = NULL;
5552                         if (p->fbo_reflection)
5553                                 R_Mesh_DestroyFramebufferObject(p->fbo_reflection);
5554                         p->fbo_reflection = 0;
5555                         if (p->texture_camera)
5556                                 R_FreeTexture(p->texture_camera);
5557                         p->texture_camera = NULL;
5558                         if (p->fbo_camera)
5559                                 R_Mesh_DestroyFramebufferObject(p->fbo_camera);
5560                         p->fbo_camera = 0;
5561                 }
5562                 memset(&r_fb.water, 0, sizeof(r_fb.water));
5563                 r_fb.water.texturewidth = texturewidth;
5564                 r_fb.water.textureheight = textureheight;
5565                 r_fb.water.camerawidth = camerawidth;
5566                 r_fb.water.cameraheight = cameraheight;
5567         }
5568
5569         if (r_fb.water.texturewidth)
5570         {
5571                 int scaledwidth, scaledheight;
5572
5573                 r_fb.water.enabled = true;
5574
5575                 // water resolution is usually reduced
5576                 r_fb.water.waterwidth = (int)bound(1, r_refdef.view.width * r_water_resolutionmultiplier.value, r_refdef.view.width);
5577                 r_fb.water.waterheight = (int)bound(1, r_refdef.view.height * r_water_resolutionmultiplier.value, r_refdef.view.height);
5578                 R_GetScaledViewSize(r_fb.water.waterwidth, r_fb.water.waterheight, &scaledwidth, &scaledheight);
5579
5580                 // set up variables that will be used in shader setup
5581                 r_fb.water.screenscale[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5582                 r_fb.water.screenscale[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5583                 r_fb.water.screencenter[0] = 0.5f * (float)scaledwidth / (float)r_fb.water.texturewidth;
5584                 r_fb.water.screencenter[1] = 0.5f * (float)scaledheight / (float)r_fb.water.textureheight;
5585         }
5586
5587         r_fb.water.maxwaterplanes = MAX_WATERPLANES;
5588         r_fb.water.numwaterplanes = 0;
5589 }
5590
5591 void R_Water_AddWaterPlane(msurface_t *surface, int entno)
5592 {
5593         int planeindex, bestplaneindex, vertexindex;
5594         vec3_t mins, maxs, normal, center, v, n;
5595         vec_t planescore, bestplanescore;
5596         mplane_t plane;
5597         r_waterstate_waterplane_t *p;
5598         texture_t *t = R_GetCurrentTexture(surface->texture);
5599
5600         rsurface.texture = t;
5601         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, 1, ((const msurface_t **)&surface));
5602         // if the model has no normals, it's probably off-screen and they were not generated, so don't add it anyway
5603         if (!rsurface.batchnormal3f || rsurface.batchnumvertices < 1)
5604                 return;
5605         // average the vertex normals, find the surface bounds (after deformvertexes)
5606         Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f, v);
5607         Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f, n);
5608         VectorCopy(n, normal);
5609         VectorCopy(v, mins);
5610         VectorCopy(v, maxs);
5611         for (vertexindex = 1;vertexindex < rsurface.batchnumvertices;vertexindex++)
5612         {
5613                 Matrix4x4_Transform(&rsurface.matrix, rsurface.batchvertex3f + vertexindex*3, v);
5614                 Matrix4x4_Transform3x3(&rsurface.matrix, rsurface.batchnormal3f + vertexindex*3, n);
5615                 VectorAdd(normal, n, normal);
5616                 mins[0] = min(mins[0], v[0]);
5617                 mins[1] = min(mins[1], v[1]);
5618                 mins[2] = min(mins[2], v[2]);
5619                 maxs[0] = max(maxs[0], v[0]);
5620                 maxs[1] = max(maxs[1], v[1]);
5621                 maxs[2] = max(maxs[2], v[2]);
5622         }
5623         VectorNormalize(normal);
5624         VectorMAM(0.5f, mins, 0.5f, maxs, center);
5625
5626         VectorCopy(normal, plane.normal);
5627         VectorNormalize(plane.normal);
5628         plane.dist = DotProduct(center, plane.normal);
5629         PlaneClassify(&plane);
5630         if (PlaneDiff(r_refdef.view.origin, &plane) < 0)
5631         {
5632                 // skip backfaces (except if nocullface is set)
5633 //              if (!(t->currentmaterialflags & MATERIALFLAG_NOCULLFACE))
5634 //                      return;
5635                 VectorNegate(plane.normal, plane.normal);
5636                 plane.dist *= -1;
5637                 PlaneClassify(&plane);
5638         }
5639
5640
5641         // find a matching plane if there is one
5642         bestplaneindex = -1;
5643         bestplanescore = 1048576.0f;
5644         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5645         {
5646                 if(p->camera_entity == t->camera_entity)
5647                 {
5648                         planescore = 1.0f - DotProduct(plane.normal, p->plane.normal) + fabs(plane.dist - p->plane.dist) * 0.001f;
5649                         if (bestplaneindex < 0 || bestplanescore > planescore)
5650                         {
5651                                 bestplaneindex = planeindex;
5652                                 bestplanescore = planescore;
5653                         }
5654                 }
5655         }
5656         planeindex = bestplaneindex;
5657         p = r_fb.water.waterplanes + planeindex;
5658
5659         // if this surface does not fit any known plane rendered this frame, add one
5660         if ((planeindex < 0 || bestplanescore > 0.001f) && r_fb.water.numwaterplanes < r_fb.water.maxwaterplanes)
5661         {
5662                 // store the new plane
5663                 planeindex = r_fb.water.numwaterplanes++;
5664                 p = r_fb.water.waterplanes + planeindex;
5665                 p->plane = plane;
5666                 // clear materialflags and pvs
5667                 p->materialflags = 0;
5668                 p->pvsvalid = false;
5669                 p->camera_entity = t->camera_entity;
5670                 VectorCopy(mins, p->mins);
5671                 VectorCopy(maxs, p->maxs);
5672         }
5673         else
5674         {
5675                 // merge mins/maxs when we're adding this surface to the plane
5676                 p->mins[0] = min(p->mins[0], mins[0]);
5677                 p->mins[1] = min(p->mins[1], mins[1]);
5678                 p->mins[2] = min(p->mins[2], mins[2]);
5679                 p->maxs[0] = max(p->maxs[0], maxs[0]);
5680                 p->maxs[1] = max(p->maxs[1], maxs[1]);
5681                 p->maxs[2] = max(p->maxs[2], maxs[2]);
5682         }
5683         // merge this surface's materialflags into the waterplane
5684         p->materialflags |= t->currentmaterialflags;
5685         if(!(p->materialflags & MATERIALFLAG_CAMERA))
5686         {
5687                 // merge this surface's PVS into the waterplane
5688                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA) && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS
5689                  && r_refdef.scene.worldmodel->brush.PointInLeaf && r_refdef.scene.worldmodel->brush.PointInLeaf(r_refdef.scene.worldmodel, center)->clusterindex >= 0)
5690                 {
5691                         r_refdef.scene.worldmodel->brush.FatPVS(r_refdef.scene.worldmodel, center, 2, p->pvsbits, sizeof(p->pvsbits), p->pvsvalid);
5692                         p->pvsvalid = true;
5693                 }
5694         }
5695 }
5696
5697 extern cvar_t r_drawparticles;
5698 extern cvar_t r_drawdecals;
5699
5700 static void R_Water_ProcessPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
5701 {
5702         int myscissor[4];
5703         r_refdef_view_t originalview;
5704         r_refdef_view_t myview;
5705         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;
5706         r_waterstate_waterplane_t *p;
5707         vec3_t visorigin;
5708         qboolean usewaterfbo = (r_viewfbo.integer >= 1 || r_water_fbo.integer >= 1) && vid.support.ext_framebuffer_object && vid.samples < 2;
5709         char vabuf[1024];
5710
5711         originalview = r_refdef.view;
5712
5713         // lowquality hack, temporarily shut down some cvars and restore afterwards
5714         qualityreduction = r_water_lowquality.integer;
5715         if (qualityreduction > 0)
5716         {
5717                 if (qualityreduction >= 1)
5718                 {
5719                         old_r_shadows = r_shadows.integer;
5720                         old_r_worldrtlight = r_shadow_realtime_world.integer;
5721                         old_r_dlight = r_shadow_realtime_dlight.integer;
5722                         Cvar_SetValueQuick(&r_shadows, 0);
5723                         Cvar_SetValueQuick(&r_shadow_realtime_world, 0);
5724                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, 0);
5725                 }
5726                 if (qualityreduction >= 2)
5727                 {
5728                         old_r_dynamic = r_dynamic.integer;
5729                         old_r_particles = r_drawparticles.integer;
5730                         old_r_decals = r_drawdecals.integer;
5731                         Cvar_SetValueQuick(&r_dynamic, 0);
5732                         Cvar_SetValueQuick(&r_drawparticles, 0);
5733                         Cvar_SetValueQuick(&r_drawdecals, 0);
5734                 }
5735         }
5736
5737         // make sure enough textures are allocated
5738         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5739         {
5740                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5741                 {
5742                         if (!p->texture_refraction)
5743                                 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);
5744                         if (!p->texture_refraction)
5745                                 goto error;
5746                         if (usewaterfbo)
5747                         {
5748                                 if (r_fb.water.depthtexture == NULL)
5749                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5750                                 if (p->fbo_refraction == 0)
5751                                         p->fbo_refraction = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_refraction, NULL, NULL, NULL);
5752                         }
5753                 }
5754                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5755                 {
5756                         if (!p->texture_camera)
5757                                 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);
5758                         if (!p->texture_camera)
5759                                 goto error;
5760                         if (usewaterfbo)
5761                         {
5762                                 if (r_fb.water.depthtexture == NULL)
5763                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5764                                 if (p->fbo_camera == 0)
5765                                         p->fbo_camera = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_camera, NULL, NULL, NULL);
5766                         }
5767                 }
5768
5769                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5770                 {
5771                         if (!p->texture_reflection)
5772                                 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);
5773                         if (!p->texture_reflection)
5774                                 goto error;
5775                         if (usewaterfbo)
5776                         {
5777                                 if (r_fb.water.depthtexture == NULL)
5778                                         r_fb.water.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "waterviewdepth", r_fb.water.texturewidth, r_fb.water.textureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
5779                                 if (p->fbo_reflection == 0)
5780                                         p->fbo_reflection = R_Mesh_CreateFramebufferObject(r_fb.water.depthtexture, p->texture_reflection, NULL, NULL, NULL);
5781                         }
5782                 }
5783         }
5784
5785         // render views
5786         r_refdef.view = originalview;
5787         r_refdef.view.showdebug = false;
5788         r_refdef.view.width = r_fb.water.waterwidth;
5789         r_refdef.view.height = r_fb.water.waterheight;
5790         r_refdef.view.useclipplane = true;
5791         myview = r_refdef.view;
5792         r_fb.water.renderingscene = true;
5793         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
5794         {
5795                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION))
5796                 {
5797                         r_refdef.view = myview;
5798                         if(r_water_scissormode.integer)
5799                         {
5800                                 R_SetupView(true, p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5801                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5802                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5803                         }
5804
5805                         // render reflected scene and copy into texture
5806                         Matrix4x4_Reflect(&r_refdef.view.matrix, p->plane.normal[0], p->plane.normal[1], p->plane.normal[2], p->plane.dist, -2);
5807                         // update the r_refdef.view.origin because otherwise the sky renders at the wrong location (amongst other problems)
5808                         Matrix4x4_OriginFromMatrix(&r_refdef.view.matrix, r_refdef.view.origin);
5809                         r_refdef.view.clipplane = p->plane;
5810                         // reverse the cullface settings for this render
5811                         r_refdef.view.cullface_front = GL_FRONT;
5812                         r_refdef.view.cullface_back = GL_BACK;
5813                         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.num_pvsclusterbytes)
5814                         {
5815                                 r_refdef.view.usecustompvs = true;
5816                                 if (p->pvsvalid)
5817                                         memcpy(r_refdef.viewcache.world_pvsbits, p->pvsbits, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5818                                 else
5819                                         memset(r_refdef.viewcache.world_pvsbits, 0xFF, r_refdef.scene.worldmodel->brush.num_pvsclusterbytes);
5820                         }
5821
5822                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 2;
5823                         R_ResetViewRendering3D(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5824                         R_ClearScreen(r_refdef.fogenabled);
5825                         if(r_water_scissormode.integer & 2)
5826                                 R_View_UpdateWithScissor(myscissor);
5827                         else
5828                                 R_View_Update();
5829                         if(r_water_scissormode.integer & 1)
5830                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5831                         R_RenderScene(p->fbo_reflection, r_fb.water.depthtexture, p->texture_reflection);
5832
5833                         if (!p->fbo_reflection)
5834                                 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);
5835                         r_fb.water.hideplayer = false;
5836                 }
5837
5838                 // render the normal view scene and copy into texture
5839                 // (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)
5840                 if (p->materialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
5841                 {
5842                         r_refdef.view = myview;
5843                         if(r_water_scissormode.integer)
5844                         {
5845                                 R_SetupView(true, p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5846                                 if(R_ScissorForBBox(p->mins, p->maxs, myscissor))
5847                                         continue; // FIXME the plane then still may get rendered but with broken texture, but it sure won't be visible
5848                         }
5849
5850                         r_fb.water.hideplayer = r_water_hideplayer.integer >= 1;
5851
5852                         r_refdef.view.clipplane = p->plane;
5853                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5854                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5855
5856                         if((p->materialflags & MATERIALFLAG_CAMERA) && p->camera_entity)
5857                         {
5858                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5859                                 r_fb.water.hideplayer = false; // we don't want to hide the player model from these ones
5860                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5861                                 R_RenderView_UpdateViewVectors();
5862                                 if(r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5863                                 {
5864                                         r_refdef.view.usecustompvs = true;
5865                                         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);
5866                                 }
5867                         }
5868
5869                         PlaneClassify(&r_refdef.view.clipplane);
5870
5871                         R_ResetViewRendering3D(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5872                         R_ClearScreen(r_refdef.fogenabled);
5873                         if(r_water_scissormode.integer & 2)
5874                                 R_View_UpdateWithScissor(myscissor);
5875                         else
5876                                 R_View_Update();
5877                         if(r_water_scissormode.integer & 1)
5878                                 GL_Scissor(myscissor[0], myscissor[1], myscissor[2], myscissor[3]);
5879                         R_RenderScene(p->fbo_refraction, r_fb.water.depthtexture, p->texture_refraction);
5880
5881                         if (!p->fbo_refraction)
5882                                 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);
5883                         r_fb.water.hideplayer = false;
5884                 }
5885                 else if (p->materialflags & MATERIALFLAG_CAMERA)
5886                 {
5887                         r_refdef.view = myview;
5888
5889                         r_refdef.view.clipplane = p->plane;
5890                         VectorNegate(r_refdef.view.clipplane.normal, r_refdef.view.clipplane.normal);
5891                         r_refdef.view.clipplane.dist = -r_refdef.view.clipplane.dist;
5892
5893                         r_refdef.view.width = r_fb.water.camerawidth;
5894                         r_refdef.view.height = r_fb.water.cameraheight;
5895                         r_refdef.view.frustum_x = 1; // tan(45 * M_PI / 180.0);
5896                         r_refdef.view.frustum_y = 1; // tan(45 * M_PI / 180.0);
5897                         r_refdef.view.ortho_x = 90; // abused as angle by VM_CL_R_SetView
5898                         r_refdef.view.ortho_y = 90; // abused as angle by VM_CL_R_SetView
5899
5900                         if(p->camera_entity)
5901                         {
5902                                 // we need to perform a matrix transform to render the view... so let's get the transformation matrix
5903                                 CL_VM_TransformView(p->camera_entity - MAX_EDICTS, &r_refdef.view.matrix, &r_refdef.view.clipplane, visorigin);
5904                         }
5905
5906                         // note: all of the view is used for displaying... so
5907                         // there is no use in scissoring
5908
5909                         // reverse the cullface settings for this render
5910                         r_refdef.view.cullface_front = GL_FRONT;
5911                         r_refdef.view.cullface_back = GL_BACK;
5912                         // also reverse the view matrix
5913                         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
5914                         R_RenderView_UpdateViewVectors();
5915                         if(p->camera_entity && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->brush.FatPVS)
5916                         {
5917                                 r_refdef.view.usecustompvs = true;
5918                                 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);
5919                         }
5920                         
5921                         // camera needs no clipplane
5922                         r_refdef.view.useclipplane = false;
5923
5924                         PlaneClassify(&r_refdef.view.clipplane);
5925
5926                         r_fb.water.hideplayer = false;
5927
5928                         R_ResetViewRendering3D(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5929                         R_ClearScreen(r_refdef.fogenabled);
5930                         R_View_Update();
5931                         R_RenderScene(p->fbo_camera, r_fb.water.depthtexture, p->texture_camera);
5932
5933                         if (!p->fbo_camera)
5934                                 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);
5935                         r_fb.water.hideplayer = false;
5936                 }
5937
5938         }
5939         if(vid.renderpath==RENDERPATH_SOFT) DPSOFTRAST_ClipPlane(0, 0, 0, 1);
5940         r_fb.water.renderingscene = false;
5941         r_refdef.view = originalview;
5942         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
5943         if (!r_fb.water.depthtexture)
5944                 R_ClearScreen(r_refdef.fogenabled);
5945         R_View_Update();
5946         goto finish;
5947 error:
5948         r_refdef.view = originalview;
5949         r_fb.water.renderingscene = false;
5950         Cvar_SetValueQuick(&r_water, 0);
5951         Con_Printf("R_Water_ProcessPlanes: Error: texture creation failed!  Turned off r_water.\n");
5952 finish:
5953         // lowquality hack, restore cvars
5954         if (qualityreduction > 0)
5955         {
5956                 if (qualityreduction >= 1)
5957                 {
5958                         Cvar_SetValueQuick(&r_shadows, old_r_shadows);
5959                         Cvar_SetValueQuick(&r_shadow_realtime_world, old_r_worldrtlight);
5960                         Cvar_SetValueQuick(&r_shadow_realtime_dlight, old_r_dlight);
5961                 }
5962                 if (qualityreduction >= 2)
5963                 {
5964                         Cvar_SetValueQuick(&r_dynamic, old_r_dynamic);
5965                         Cvar_SetValueQuick(&r_drawparticles, old_r_particles);
5966                         Cvar_SetValueQuick(&r_drawdecals, old_r_decals);
5967                 }
5968         }
5969 }
5970
5971 static void R_Bloom_StartFrame(void)
5972 {
5973         int i;
5974         int bloomtexturewidth, bloomtextureheight, screentexturewidth, screentextureheight;
5975         int viewwidth, viewheight;
5976         qboolean useviewfbo = r_viewfbo.integer >= 1 && vid.support.ext_framebuffer_object && vid.samples < 2;
5977         textype_t textype = TEXTYPE_COLORBUFFER;
5978
5979         switch (vid.renderpath)
5980         {
5981         case RENDERPATH_GL20:
5982                 r_fb.usedepthtextures = r_usedepthtextures.integer != 0;
5983                 if (vid.support.ext_framebuffer_object)
5984                 {
5985                         if (r_viewfbo.integer == 2) textype = TEXTYPE_COLORBUFFER16F;
5986                         if (r_viewfbo.integer == 3) textype = TEXTYPE_COLORBUFFER32F;
5987                 }
5988                 break;
5989         case RENDERPATH_GL11:
5990         case RENDERPATH_GL13:
5991         case RENDERPATH_GLES1:
5992         case RENDERPATH_GLES2:
5993         case RENDERPATH_D3D9:
5994         case RENDERPATH_D3D10:
5995         case RENDERPATH_D3D11:
5996                 r_fb.usedepthtextures = false;
5997                 break;
5998         case RENDERPATH_SOFT:
5999                 r_fb.usedepthtextures = true;
6000                 break;
6001         }
6002
6003         if (r_viewscale_fpsscaling.integer)
6004         {
6005                 double actualframetime;
6006                 double targetframetime;
6007                 double adjust;
6008                 actualframetime = r_refdef.lastdrawscreentime;
6009                 targetframetime = (1.0 / r_viewscale_fpsscaling_target.value);
6010                 adjust = (targetframetime - actualframetime) * r_viewscale_fpsscaling_multiply.value;
6011                 adjust = bound(-r_viewscale_fpsscaling_stepmax.value, adjust, r_viewscale_fpsscaling_stepmax.value);
6012                 if (r_viewscale_fpsscaling_stepsize.value > 0)
6013                         adjust = (int)(adjust / r_viewscale_fpsscaling_stepsize.value) * r_viewscale_fpsscaling_stepsize.value;
6014                 viewscalefpsadjusted += adjust;
6015                 viewscalefpsadjusted = bound(r_viewscale_fpsscaling_min.value, viewscalefpsadjusted, 1.0f);
6016         }
6017         else
6018                 viewscalefpsadjusted = 1.0f;
6019
6020         R_GetScaledViewSize(r_refdef.view.width, r_refdef.view.height, &viewwidth, &viewheight);
6021
6022         switch(vid.renderpath)
6023         {
6024         case RENDERPATH_GL20:
6025         case RENDERPATH_D3D9:
6026         case RENDERPATH_D3D10:
6027         case RENDERPATH_D3D11:
6028         case RENDERPATH_SOFT:
6029         case RENDERPATH_GLES2:
6030                 break;
6031         case RENDERPATH_GL11:
6032         case RENDERPATH_GL13:
6033         case RENDERPATH_GLES1:
6034                 return;
6035         }
6036
6037         // set bloomwidth and bloomheight to the bloom resolution that will be
6038         // used (often less than the screen resolution for faster rendering)
6039         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, vid.height);
6040         r_fb.bloomheight = r_fb.bloomwidth * vid.height / vid.width;
6041         r_fb.bloomheight = bound(1, r_fb.bloomheight, vid.height);
6042         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, (int)vid.maxtexturesize_2d);
6043         r_fb.bloomheight = bound(1, r_fb.bloomheight, (int)vid.maxtexturesize_2d);
6044
6045         // calculate desired texture sizes
6046         if (vid.support.arb_texture_non_power_of_two)
6047         {
6048                 screentexturewidth = vid.width;
6049                 screentextureheight = vid.height;
6050                 bloomtexturewidth = r_fb.bloomwidth;
6051                 bloomtextureheight = r_fb.bloomheight;
6052         }
6053         else
6054         {
6055                 for (screentexturewidth  = 1;screentexturewidth  < vid.width       ;screentexturewidth  *= 2);
6056                 for (screentextureheight = 1;screentextureheight < vid.height      ;screentextureheight *= 2);
6057                 for (bloomtexturewidth   = 1;bloomtexturewidth   < r_fb.bloomwidth ;bloomtexturewidth   *= 2);
6058                 for (bloomtextureheight  = 1;bloomtextureheight  < r_fb.bloomheight;bloomtextureheight  *= 2);
6059         }
6060
6061         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))
6062         {
6063                 Cvar_SetValueQuick(&r_bloom, 0);
6064                 Cvar_SetValueQuick(&r_motionblur, 0);
6065                 Cvar_SetValueQuick(&r_damageblur, 0);
6066         }
6067
6068         if (!(r_glsl_postprocess.integer || (!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) || (v_glslgamma.integer && !vid_gammatables_trivial))
6069          && !r_bloom.integer
6070          && (R_Stereo_Active() || (r_motionblur.value <= 0 && r_damageblur.value <= 0))
6071          && !useviewfbo
6072          && r_viewscale.value == 1.0f
6073          && !r_viewscale_fpsscaling.integer)
6074                 screentexturewidth = screentextureheight = 0;
6075         if (!r_bloom.integer)
6076                 bloomtexturewidth = bloomtextureheight = 0;
6077
6078         // allocate textures as needed
6079         if (r_fb.screentexturewidth != screentexturewidth
6080          || r_fb.screentextureheight != screentextureheight
6081          || r_fb.bloomtexturewidth != bloomtexturewidth
6082          || r_fb.bloomtextureheight != bloomtextureheight
6083          || r_fb.textype != textype
6084          || useviewfbo != (r_fb.fbo != 0))
6085         {
6086                 for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6087                 {
6088                         if (r_fb.bloomtexture[i])
6089                                 R_FreeTexture(r_fb.bloomtexture[i]);
6090                         r_fb.bloomtexture[i] = NULL;
6091
6092                         if (r_fb.bloomfbo[i])
6093                                 R_Mesh_DestroyFramebufferObject(r_fb.bloomfbo[i]);
6094                         r_fb.bloomfbo[i] = 0;
6095                 }
6096
6097                 if (r_fb.fbo)
6098                         R_Mesh_DestroyFramebufferObject(r_fb.fbo);
6099                 r_fb.fbo = 0;
6100
6101                 if (r_fb.colortexture)
6102                         R_FreeTexture(r_fb.colortexture);
6103                 r_fb.colortexture = NULL;
6104
6105                 if (r_fb.depthtexture)
6106                         R_FreeTexture(r_fb.depthtexture);
6107                 r_fb.depthtexture = NULL;
6108
6109                 if (r_fb.ghosttexture)
6110                         R_FreeTexture(r_fb.ghosttexture);
6111                 r_fb.ghosttexture = NULL;
6112
6113                 r_fb.screentexturewidth = screentexturewidth;
6114                 r_fb.screentextureheight = screentextureheight;
6115                 r_fb.bloomtexturewidth = bloomtexturewidth;
6116                 r_fb.bloomtextureheight = bloomtextureheight;
6117                 r_fb.textype = textype;
6118
6119                 if (r_fb.screentexturewidth && r_fb.screentextureheight)
6120                 {
6121                         if (r_motionblur.value > 0 || r_damageblur.value > 0)
6122                                 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);
6123                         r_fb.ghosttexture_valid = false;
6124                         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);
6125                         if (useviewfbo)
6126                         {
6127                                 r_fb.depthtexture = R_LoadTextureRenderBuffer(r_main_texturepool, "framebufferdepth", r_fb.screentexturewidth, r_fb.screentextureheight, TEXTYPE_DEPTHBUFFER24STENCIL8);
6128                                 r_fb.fbo = R_Mesh_CreateFramebufferObject(r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6129                                 R_Mesh_SetRenderTargets(r_fb.fbo, r_fb.depthtexture, r_fb.colortexture, NULL, NULL, NULL);
6130                         }
6131                 }
6132
6133                 if (r_fb.bloomtexturewidth && r_fb.bloomtextureheight)
6134                 {
6135                         for (i = 0;i < (int)(sizeof(r_fb.bloomtexture)/sizeof(r_fb.bloomtexture[i]));i++)
6136                         {
6137                                 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);
6138                                 if (useviewfbo)
6139                                         r_fb.bloomfbo[i] = R_Mesh_CreateFramebufferObject(NULL, r_fb.bloomtexture[i], NULL, NULL, NULL);
6140                         }
6141                 }
6142         }
6143
6144         // bloom texture is a different resolution
6145         r_fb.bloomwidth = bound(1, r_bloom_resolution.integer, r_refdef.view.height);
6146         r_fb.bloomheight = r_fb.bloomwidth * r_refdef.view.height / r_refdef.view.width;
6147         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_refdef.view.height);
6148         r_fb.bloomwidth = bound(1, r_fb.bloomwidth, r_fb.bloomtexturewidth);
6149         r_fb.bloomheight = bound(1, r_fb.bloomheight, r_fb.bloomtextureheight);
6150
6151         // set up a texcoord array for the full resolution screen image
6152         // (we have to keep this around to copy back during final render)
6153         r_fb.screentexcoord2f[0] = 0;
6154         r_fb.screentexcoord2f[1] = (float)viewheight    / (float)r_fb.screentextureheight;
6155         r_fb.screentexcoord2f[2] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6156         r_fb.screentexcoord2f[3] = (float)viewheight    / (float)r_fb.screentextureheight;
6157         r_fb.screentexcoord2f[4] = (float)viewwidth     / (float)r_fb.screentexturewidth;
6158         r_fb.screentexcoord2f[5] = 0;
6159         r_fb.screentexcoord2f[6] = 0;
6160         r_fb.screentexcoord2f[7] = 0;
6161
6162         // set up a texcoord array for the reduced resolution bloom image
6163         // (which will be additive blended over the screen image)
6164         r_fb.bloomtexcoord2f[0] = 0;
6165         r_fb.bloomtexcoord2f[1] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6166         r_fb.bloomtexcoord2f[2] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6167         r_fb.bloomtexcoord2f[3] = (float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6168         r_fb.bloomtexcoord2f[4] = (float)r_fb.bloomwidth  / (float)r_fb.bloomtexturewidth;
6169         r_fb.bloomtexcoord2f[5] = 0;
6170         r_fb.bloomtexcoord2f[6] = 0;
6171         r_fb.bloomtexcoord2f[7] = 0;
6172
6173         switch(vid.renderpath)
6174         {
6175         case RENDERPATH_GL11:
6176         case RENDERPATH_GL13:
6177         case RENDERPATH_GL20:
6178         case RENDERPATH_SOFT:
6179         case RENDERPATH_GLES1:
6180         case RENDERPATH_GLES2:
6181                 break;
6182         case RENDERPATH_D3D9:
6183         case RENDERPATH_D3D10:
6184         case RENDERPATH_D3D11:
6185                 {
6186                         int i;
6187                         for (i = 0;i < 4;i++)
6188                         {
6189                                 r_fb.screentexcoord2f[i*2+0] += 0.5f / (float)r_fb.screentexturewidth;
6190                                 r_fb.screentexcoord2f[i*2+1] += 0.5f / (float)r_fb.screentextureheight;
6191                                 r_fb.bloomtexcoord2f[i*2+0] += 0.5f / (float)r_fb.bloomtexturewidth;
6192                                 r_fb.bloomtexcoord2f[i*2+1] += 0.5f / (float)r_fb.bloomtextureheight;
6193                         }
6194                 }
6195                 break;
6196         }
6197
6198         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);
6199
6200         if (r_fb.fbo)
6201                 r_refdef.view.clear = true;
6202 }
6203
6204 static void R_Bloom_MakeTexture(void)
6205 {
6206         int x, range, dir;
6207         float xoffset, yoffset, r, brighten;
6208         rtexture_t *intex;
6209         float colorscale = r_bloom_colorscale.value;
6210
6211         r_refdef.stats.bloom++;
6212
6213         if (!r_fb.fbo)
6214         {
6215                 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);
6216                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6217         }
6218
6219         // scale down screen texture to the bloom texture size
6220         CHECKGLERROR
6221         r_fb.bloomindex = 0;
6222         R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6223         R_SetViewport(&r_fb.bloomviewport);
6224         GL_BlendFunc(GL_ONE, GL_ZERO);
6225         GL_Color(colorscale, colorscale, colorscale, 1);
6226         // 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...
6227         switch(vid.renderpath)
6228         {
6229         case RENDERPATH_GL11:
6230         case RENDERPATH_GL13:
6231         case RENDERPATH_GL20:
6232         case RENDERPATH_GLES1:
6233         case RENDERPATH_GLES2:
6234         case RENDERPATH_SOFT:
6235                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6236                 break;
6237         case RENDERPATH_D3D9:
6238         case RENDERPATH_D3D10:
6239         case RENDERPATH_D3D11:
6240                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6241                 break;
6242         }
6243         // TODO: do boxfilter scale-down in shader?
6244         R_SetupShader_Generic(r_fb.colortexture, NULL, GL_MODULATE, 1, false, true, true);
6245         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6246         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6247
6248         // we now have a properly scaled bloom image
6249         if (!r_fb.bloomfbo[r_fb.bloomindex])
6250         {
6251                 // copy it into the bloom texture
6252                 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);
6253                 r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6254         }
6255
6256         // multiply bloom image by itself as many times as desired
6257         for (x = 1;x < min(r_bloom_colorexponent.value, 32);)
6258         {
6259                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6260                 r_fb.bloomindex ^= 1;
6261                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6262                 x *= 2;
6263                 r = bound(0, r_bloom_colorexponent.value / x, 1); // always 0.5 to 1
6264                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6265                 {
6266                         GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // square it and multiply by two
6267                         GL_Color(r,r,r,1); // apply fix factor
6268                 }
6269                 else
6270                 {
6271                         if(x <= 2)
6272                                 GL_Clear(GL_COLOR_BUFFER_BIT, NULL, 1.0f, 128);
6273                         GL_BlendFunc(GL_SRC_COLOR, GL_ZERO); // square it
6274                         GL_Color(1,1,1,1); // no fix factor supported here
6275                 }
6276                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.bloomtexcoord2f);
6277                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6278                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6279                 r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6280
6281                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6282                 {
6283                         // copy the darkened image to a texture
6284                         R_Mesh_CopyToTexture(r_fb.bloomtexture[r_fb.bloomindex], 0, 0, r_fb.bloomviewport.x, r_fb.bloomviewport.y, r_fb.bloomviewport.width, r_fb.bloomviewport.height);
6285                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6286                 }
6287         }
6288
6289         range = r_bloom_blur.integer * r_fb.bloomwidth / 320;
6290         brighten = r_bloom_brighten.value;
6291         brighten = sqrt(brighten);
6292         if(range >= 1)
6293                 brighten *= (3 * range) / (2 * range - 1); // compensate for the "dot particle"
6294
6295         for (dir = 0;dir < 2;dir++)
6296         {
6297                 intex = r_fb.bloomtexture[r_fb.bloomindex];
6298                 r_fb.bloomindex ^= 1;
6299                 R_Mesh_SetRenderTargets(r_fb.bloomfbo[r_fb.bloomindex], NULL, r_fb.bloomtexture[r_fb.bloomindex], NULL, NULL, NULL);
6300                 // blend on at multiple vertical offsets to achieve a vertical blur
6301                 // TODO: do offset blends using GLSL
6302                 // TODO instead of changing the texcoords, change the target positions to prevent artifacts at edges
6303                 GL_BlendFunc(GL_ONE, GL_ZERO);
6304                 R_SetupShader_Generic(intex, NULL, GL_MODULATE, 1, false, true, false);
6305                 for (x = -range;x <= range;x++)
6306                 {
6307                         if (!dir){xoffset = 0;yoffset = x;}
6308                         else {xoffset = x;yoffset = 0;}
6309                         xoffset /= (float)r_fb.bloomtexturewidth;
6310                         yoffset /= (float)r_fb.bloomtextureheight;
6311                         // compute a texcoord array with the specified x and y offset
6312                         r_fb.offsettexcoord2f[0] = xoffset+0;
6313                         r_fb.offsettexcoord2f[1] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6314                         r_fb.offsettexcoord2f[2] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6315                         r_fb.offsettexcoord2f[3] = yoffset+(float)r_fb.bloomheight / (float)r_fb.bloomtextureheight;
6316                         r_fb.offsettexcoord2f[4] = xoffset+(float)r_fb.bloomwidth / (float)r_fb.bloomtexturewidth;
6317                         r_fb.offsettexcoord2f[5] = yoffset+0;
6318                         r_fb.offsettexcoord2f[6] = xoffset+0;
6319                         r_fb.offsettexcoord2f[7] = yoffset+0;
6320                         // this r value looks like a 'dot' particle, fading sharply to
6321                         // black at the edges
6322                         // (probably not realistic but looks good enough)
6323                         //r = ((range*range+1)/((float)(x*x+1)))/(range*2+1);
6324                         //r = brighten/(range*2+1);
6325                         r = brighten / (range * 2 + 1);
6326                         if(range >= 1)
6327                                 r *= (1 - x*x/(float)(range*range));
6328                         GL_Color(r, r, r, 1);
6329                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.offsettexcoord2f);
6330                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6331                         r_refdef.stats.bloom_drawpixels += r_fb.bloomwidth * r_fb.bloomheight;
6332                         GL_BlendFunc(GL_ONE, GL_ONE);
6333                 }
6334
6335                 if (!r_fb.bloomfbo[r_fb.bloomindex])
6336                 {
6337                         // copy the vertically or horizontally blurred bloom view to a texture
6338                         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);
6339                         r_refdef.stats.bloom_copypixels += r_fb.bloomviewport.width * r_fb.bloomviewport.height;
6340                 }
6341         }
6342 }
6343
6344 static void R_BlendView(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6345 {
6346         unsigned int permutation;
6347         float uservecs[4][4];
6348
6349         switch (vid.renderpath)
6350         {
6351         case RENDERPATH_GL20:
6352         case RENDERPATH_D3D9:
6353         case RENDERPATH_D3D10:
6354         case RENDERPATH_D3D11:
6355         case RENDERPATH_SOFT:
6356         case RENDERPATH_GLES2:
6357                 permutation =
6358                           (r_fb.bloomtexture[r_fb.bloomindex] ? SHADERPERMUTATION_BLOOM : 0)
6359                         | (r_refdef.viewblend[3] > 0 ? SHADERPERMUTATION_VIEWTINT : 0)
6360                         | ((v_glslgamma.value && !vid_gammatables_trivial) ? SHADERPERMUTATION_GAMMARAMPS : 0)
6361                         | (r_glsl_postprocess.integer ? SHADERPERMUTATION_POSTPROCESSING : 0)
6362                         | ((!R_Stereo_ColorMasking() && r_glsl_saturation.value != 1) ? SHADERPERMUTATION_SATURATION : 0);
6363
6364                 if (r_fb.colortexture)
6365                 {
6366                         if (!r_fb.fbo)
6367                         {
6368                                 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);
6369                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6370                         }
6371
6372                         if(!R_Stereo_Active() && (r_motionblur.value > 0 || r_damageblur.value > 0) && r_fb.ghosttexture)
6373                         {
6374                                 // declare variables
6375                                 float blur_factor, blur_mouseaccel, blur_velocity;
6376                                 static float blur_average; 
6377                                 static vec3_t blur_oldangles; // used to see how quickly the mouse is moving
6378
6379                                 // set a goal for the factoring
6380                                 blur_velocity = bound(0, (VectorLength(cl.movement_velocity) - r_motionblur_velocityfactor_minspeed.value) 
6381                                         / max(1, r_motionblur_velocityfactor_maxspeed.value - r_motionblur_velocityfactor_minspeed.value), 1);
6382                                 blur_mouseaccel = bound(0, ((fabs(VectorLength(cl.viewangles) - VectorLength(blur_oldangles)) * 10) - r_motionblur_mousefactor_minspeed.value) 
6383                                         / max(1, r_motionblur_mousefactor_maxspeed.value - r_motionblur_mousefactor_minspeed.value), 1);
6384                                 blur_factor = ((blur_velocity * r_motionblur_velocityfactor.value) 
6385                                         + (blur_mouseaccel * r_motionblur_mousefactor.value));
6386
6387                                 // from the goal, pick an averaged value between goal and last value
6388                                 cl.motionbluralpha = bound(0, (cl.time - cl.oldtime) / max(0.001, r_motionblur_averaging.value), 1);
6389                                 blur_average = blur_average * (1 - cl.motionbluralpha) + blur_factor * cl.motionbluralpha;
6390
6391                                 // enforce minimum amount of blur 
6392                                 blur_factor = blur_average * (1 - r_motionblur_minblur.value) + r_motionblur_minblur.value;
6393
6394                                 //Con_Printf("motionblur: direct factor: %f, averaged factor: %f, velocity: %f, mouse accel: %f \n", blur_factor, blur_average, blur_velocity, blur_mouseaccel);
6395
6396                                 // calculate values into a standard alpha
6397                                 cl.motionbluralpha = 1 - exp(-
6398                                                 (
6399                                                  (r_motionblur.value * blur_factor / 80)
6400                                                  +
6401                                                  (r_damageblur.value * (cl.cshifts[CSHIFT_DAMAGE].percent / 1600))
6402                                                 )
6403                                                 /
6404                                                 max(0.0001, cl.time - cl.oldtime) // fps independent
6405                                           );
6406
6407                                 // randomization for the blur value to combat persistent ghosting
6408                                 cl.motionbluralpha *= lhrandom(1 - r_motionblur_randomize.value, 1 + r_motionblur_randomize.value);
6409                                 cl.motionbluralpha = bound(0, cl.motionbluralpha, r_motionblur_maxblur.value);
6410
6411                                 // apply the blur
6412                                 R_ResetViewRendering2D(fbo, depthtexture, colortexture);
6413                                 if (cl.motionbluralpha > 0 && !r_refdef.envmap && r_fb.ghosttexture_valid)
6414                                 {
6415                                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6416                                         GL_Color(1, 1, 1, cl.motionbluralpha);
6417                                         switch(vid.renderpath)
6418                                         {
6419                                         case RENDERPATH_GL11:
6420                                         case RENDERPATH_GL13:
6421                                         case RENDERPATH_GL20:
6422                                         case RENDERPATH_GLES1:
6423                                         case RENDERPATH_GLES2:
6424                                         case RENDERPATH_SOFT:
6425                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, r_fb.screentexcoord2f);
6426                                                 break;
6427                                         case RENDERPATH_D3D9:
6428                                         case RENDERPATH_D3D10:
6429                                         case RENDERPATH_D3D11:
6430                                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_d3dscreenvertex3f, NULL, r_fb.screentexcoord2f);
6431                                                 break;
6432                                         }
6433                                         R_SetupShader_Generic(r_fb.ghosttexture, NULL, GL_MODULATE, 1, false, true, true);
6434                                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6435                                         r_refdef.stats.bloom_drawpixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6436                                 }
6437
6438                                 // updates old view angles for next pass
6439                                 VectorCopy(cl.viewangles, blur_oldangles);
6440
6441                                 // copy view into the ghost texture
6442                                 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);
6443                                 r_refdef.stats.bloom_copypixels += r_refdef.view.viewport.width * r_refdef.view.viewport.height;
6444                                 r_fb.ghosttexture_valid = true;
6445                         }
6446                 }
6447                 else
6448                 {
6449                         // no r_fb.colortexture means we're rendering to the real fb
6450                         // we may still have to do view tint...
6451                         if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6452                         {
6453                                 // apply a color tint to the whole view
6454                                 R_ResetViewRendering2D(0, NULL, NULL);
6455                                 GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6456                                 R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6457                                 R_SetupShader_Generic_NoTexture(false, true);
6458                                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6459                                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6460                         }
6461                         break; // no screen processing, no bloom, skip it
6462                 }
6463
6464                 if (r_fb.bloomtexture[0])
6465                 {
6466                         // make the bloom texture
6467                         R_Bloom_MakeTexture();
6468                 }
6469
6470 #if _MSC_VER >= 1400
6471 #define sscanf sscanf_s
6472 #endif
6473                 memset(uservecs, 0, sizeof(uservecs));
6474                 if (r_glsl_postprocess_uservec1_enable.integer)
6475                         sscanf(r_glsl_postprocess_uservec1.string, "%f %f %f %f", &uservecs[0][0], &uservecs[0][1], &uservecs[0][2], &uservecs[0][3]);
6476                 if (r_glsl_postprocess_uservec2_enable.integer)
6477                         sscanf(r_glsl_postprocess_uservec2.string, "%f %f %f %f", &uservecs[1][0], &uservecs[1][1], &uservecs[1][2], &uservecs[1][3]);
6478                 if (r_glsl_postprocess_uservec3_enable.integer)
6479                         sscanf(r_glsl_postprocess_uservec3.string, "%f %f %f %f", &uservecs[2][0], &uservecs[2][1], &uservecs[2][2], &uservecs[2][3]);
6480                 if (r_glsl_postprocess_uservec4_enable.integer)
6481                         sscanf(r_glsl_postprocess_uservec4.string, "%f %f %f %f", &uservecs[3][0], &uservecs[3][1], &uservecs[3][2], &uservecs[3][3]);
6482
6483                 R_ResetViewRendering2D(0, NULL, NULL); // here we render to the real framebuffer!
6484                 GL_Color(1, 1, 1, 1);
6485                 GL_BlendFunc(GL_ONE, GL_ZERO);
6486
6487                 switch(vid.renderpath)
6488                 {
6489                 case RENDERPATH_GL20:
6490                 case RENDERPATH_GLES2:
6491                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6492                         R_SetupShader_SetPermutationGLSL(SHADERMODE_POSTPROCESS, permutation);
6493                         if (r_glsl_permutation->tex_Texture_First           >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_First     , r_fb.colortexture);
6494                         if (r_glsl_permutation->tex_Texture_Second          >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_Second    , r_fb.bloomtexture[r_fb.bloomindex]);
6495                         if (r_glsl_permutation->tex_Texture_GammaRamps      >= 0) R_Mesh_TexBind(r_glsl_permutation->tex_Texture_GammaRamps, r_texture_gammaramps       );
6496                         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]);
6497                         if (r_glsl_permutation->loc_PixelSize               >= 0) qglUniform2f(r_glsl_permutation->loc_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6498                         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]);
6499                         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]);
6500                         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]);
6501                         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]);
6502                         if (r_glsl_permutation->loc_Saturation              >= 0) qglUniform1f(r_glsl_permutation->loc_Saturation        , r_glsl_saturation.value);
6503                         if (r_glsl_permutation->loc_PixelToScreenTexCoord   >= 0) qglUniform2f(r_glsl_permutation->loc_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6504                         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);
6505                         break;
6506                 case RENDERPATH_D3D9:
6507 #ifdef SUPPORTD3D
6508                         // 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...
6509                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_d3dscreenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6510                         R_SetupShader_SetPermutationHLSL(SHADERMODE_POSTPROCESS, permutation);
6511                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6512                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6513                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6514                         hlslPSSetParameter4f(D3DPSREGISTER_ViewTintColor        , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6515                         hlslPSSetParameter2f(D3DPSREGISTER_PixelSize            , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6516                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec1             , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6517                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec2             , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6518                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec3             , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6519                         hlslPSSetParameter4f(D3DPSREGISTER_UserVec4             , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6520                         hlslPSSetParameter1f(D3DPSREGISTER_Saturation           , r_glsl_saturation.value);
6521                         hlslPSSetParameter2f(D3DPSREGISTER_PixelToScreenTexCoord, 1.0f/vid.width, 1.0/vid.height);
6522                         hlslPSSetParameter4f(D3DPSREGISTER_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6523 #endif
6524                         break;
6525                 case RENDERPATH_D3D10:
6526                         Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6527                         break;
6528                 case RENDERPATH_D3D11:
6529                         Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
6530                         break;
6531                 case RENDERPATH_SOFT:
6532                         R_Mesh_PrepareVertices_Mesh_Arrays(4, r_screenvertex3f, NULL, NULL, NULL, NULL, r_fb.screentexcoord2f, r_fb.bloomtexcoord2f);
6533                         R_SetupShader_SetPermutationSoft(SHADERMODE_POSTPROCESS, permutation);
6534                         R_Mesh_TexBind(GL20TU_FIRST     , r_fb.colortexture);
6535                         R_Mesh_TexBind(GL20TU_SECOND    , r_fb.bloomtexture[r_fb.bloomindex]);
6536                         R_Mesh_TexBind(GL20TU_GAMMARAMPS, r_texture_gammaramps       );
6537                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_ViewTintColor     , r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6538                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelSize         , 1.0/r_fb.screentexturewidth, 1.0/r_fb.screentextureheight);
6539                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec1          , uservecs[0][0], uservecs[0][1], uservecs[0][2], uservecs[0][3]);
6540                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec2          , uservecs[1][0], uservecs[1][1], uservecs[1][2], uservecs[1][3]);
6541                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec3          , uservecs[2][0], uservecs[2][1], uservecs[2][2], uservecs[2][3]);
6542                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_UserVec4          , uservecs[3][0], uservecs[3][1], uservecs[3][2], uservecs[3][3]);
6543                         DPSOFTRAST_Uniform1f(DPSOFTRAST_UNIFORM_Saturation        , r_glsl_saturation.value);
6544                         DPSOFTRAST_Uniform2f(DPSOFTRAST_UNIFORM_PixelToScreenTexCoord, 1.0f/vid.width, 1.0f/vid.height);
6545                         DPSOFTRAST_Uniform4f(DPSOFTRAST_UNIFORM_BloomColorSubtract   , r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, r_bloom_colorsubtract.value, 0.0f);
6546                         break;
6547                 default:
6548                         break;
6549                 }
6550                 R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6551                 r_refdef.stats.bloom_drawpixels += r_refdef.view.width * r_refdef.view.height;
6552                 break;
6553         case RENDERPATH_GL11:
6554         case RENDERPATH_GL13:
6555         case RENDERPATH_GLES1:
6556                 if (r_refdef.viewblend[3] >= (1.0f / 256.0f))
6557                 {
6558                         // apply a color tint to the whole view
6559                         R_ResetViewRendering2D(0, NULL, NULL);
6560                         GL_Color(r_refdef.viewblend[0], r_refdef.viewblend[1], r_refdef.viewblend[2], r_refdef.viewblend[3]);
6561                         R_Mesh_PrepareVertices_Generic_Arrays(4, r_screenvertex3f, NULL, NULL);
6562                         R_SetupShader_Generic_NoTexture(false, true);
6563                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
6564                         R_Mesh_Draw(0, 4, 0, 2, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
6565                 }
6566                 break;
6567         }
6568 }
6569
6570 matrix4x4_t r_waterscrollmatrix;
6571
6572 void R_UpdateFog(void)
6573 {
6574         // Nehahra fog
6575         if (gamemode == GAME_NEHAHRA)
6576         {
6577                 if (gl_fogenable.integer)
6578                 {
6579                         r_refdef.oldgl_fogenable = true;
6580                         r_refdef.fog_density = gl_fogdensity.value;
6581                         r_refdef.fog_red = gl_fogred.value;
6582                         r_refdef.fog_green = gl_foggreen.value;
6583                         r_refdef.fog_blue = gl_fogblue.value;
6584                         r_refdef.fog_alpha = 1;
6585                         r_refdef.fog_start = 0;
6586                         r_refdef.fog_end = gl_skyclip.value;
6587                         r_refdef.fog_height = 1<<30;
6588                         r_refdef.fog_fadedepth = 128;
6589                 }
6590                 else if (r_refdef.oldgl_fogenable)
6591                 {
6592                         r_refdef.oldgl_fogenable = false;
6593                         r_refdef.fog_density = 0;
6594                         r_refdef.fog_red = 0;
6595                         r_refdef.fog_green = 0;
6596                         r_refdef.fog_blue = 0;
6597                         r_refdef.fog_alpha = 0;
6598                         r_refdef.fog_start = 0;
6599                         r_refdef.fog_end = 0;
6600                         r_refdef.fog_height = 1<<30;
6601                         r_refdef.fog_fadedepth = 128;
6602                 }
6603         }
6604
6605         // fog parms
6606         r_refdef.fog_alpha = bound(0, r_refdef.fog_alpha, 1);
6607         r_refdef.fog_start = max(0, r_refdef.fog_start);
6608         r_refdef.fog_end = max(r_refdef.fog_start + 0.01, r_refdef.fog_end);
6609
6610         if (r_refdef.fog_density && r_drawfog.integer)
6611         {
6612                 r_refdef.fogenabled = true;
6613                 // this is the point where the fog reaches 0.9986 alpha, which we
6614                 // consider a good enough cutoff point for the texture
6615                 // (0.9986 * 256 == 255.6)
6616                 if (r_fog_exp2.integer)
6617                         r_refdef.fogrange = 32 / (r_refdef.fog_density * r_refdef.fog_density) + r_refdef.fog_start;
6618                 else
6619                         r_refdef.fogrange = 2048 / r_refdef.fog_density + r_refdef.fog_start;
6620                 r_refdef.fogrange = bound(r_refdef.fog_start, r_refdef.fogrange, r_refdef.fog_end);
6621                 r_refdef.fograngerecip = 1.0f / r_refdef.fogrange;
6622                 r_refdef.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * r_refdef.fograngerecip;
6623                 if (strcmp(r_refdef.fogheighttexturename, r_refdef.fog_height_texturename))
6624                         R_BuildFogHeightTexture();
6625                 // fog color was already set
6626                 // update the fog texture
6627                 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)
6628                         R_BuildFogTexture();
6629                 r_refdef.fog_height_texcoordscale = 1.0f / max(0.125f, r_refdef.fog_fadedepth);
6630                 r_refdef.fog_height_tablescale = r_refdef.fog_height_tablesize * r_refdef.fog_height_texcoordscale;
6631         }
6632         else
6633                 r_refdef.fogenabled = false;
6634
6635         // fog color
6636         if (r_refdef.fog_density)
6637         {
6638                 r_refdef.fogcolor[0] = r_refdef.fog_red;
6639                 r_refdef.fogcolor[1] = r_refdef.fog_green;
6640                 r_refdef.fogcolor[2] = r_refdef.fog_blue;
6641
6642                 Vector4Set(r_refdef.fogplane, 0, 0, 1, -r_refdef.fog_height);
6643                 r_refdef.fogplaneviewdist = DotProduct(r_refdef.fogplane, r_refdef.view.origin) + r_refdef.fogplane[3];
6644                 r_refdef.fogplaneviewabove = r_refdef.fogplaneviewdist >= 0;
6645                 r_refdef.fogheightfade = -0.5f/max(0.125f, r_refdef.fog_fadedepth);
6646
6647                 {
6648                         vec3_t fogvec;
6649                         VectorCopy(r_refdef.fogcolor, fogvec);
6650                         //   color.rgb *= ContrastBoost * SceneBrightness;
6651                         VectorScale(fogvec, r_refdef.view.colorscale, fogvec);
6652                         r_refdef.fogcolor[0] = bound(0.0f, fogvec[0], 1.0f);
6653                         r_refdef.fogcolor[1] = bound(0.0f, fogvec[1], 1.0f);
6654                         r_refdef.fogcolor[2] = bound(0.0f, fogvec[2], 1.0f);
6655                 }
6656         }
6657 }
6658
6659 void R_UpdateVariables(void)
6660 {
6661         R_Textures_Frame();
6662
6663         r_refdef.scene.ambient = r_ambient.value * (1.0f / 64.0f);
6664
6665         r_refdef.farclip = r_farclip_base.value;
6666         if (r_refdef.scene.worldmodel)
6667                 r_refdef.farclip += r_refdef.scene.worldmodel->radius * r_farclip_world.value * 2;
6668         r_refdef.nearclip = bound (0.001f, r_nearclip.value, r_refdef.farclip - 1.0f);
6669
6670         if (r_shadow_frontsidecasting.integer < 0 || r_shadow_frontsidecasting.integer > 1)
6671                 Cvar_SetValueQuick(&r_shadow_frontsidecasting, 1);
6672         r_refdef.polygonfactor = 0;
6673         r_refdef.polygonoffset = 0;
6674         r_refdef.shadowpolygonfactor = r_refdef.polygonfactor + r_shadow_polygonfactor.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6675         r_refdef.shadowpolygonoffset = r_refdef.polygonoffset + r_shadow_polygonoffset.value * (r_shadow_frontsidecasting.integer ? 1 : -1);
6676
6677         r_refdef.scene.rtworld = r_shadow_realtime_world.integer != 0;
6678         r_refdef.scene.rtworldshadows = r_shadow_realtime_world_shadows.integer && vid.stencil;
6679         r_refdef.scene.rtdlight = r_shadow_realtime_dlight.integer != 0 && !gl_flashblend.integer && r_dynamic.integer;
6680         r_refdef.scene.rtdlightshadows = r_refdef.scene.rtdlight && r_shadow_realtime_dlight_shadows.integer && vid.stencil;
6681         r_refdef.lightmapintensity = r_refdef.scene.rtworld ? r_shadow_realtime_world_lightmaps.value : 1;
6682         if (FAKELIGHT_ENABLED)
6683         {
6684                 r_refdef.lightmapintensity *= r_fakelight_intensity.value;
6685         }
6686         else if (r_refdef.scene.worldmodel)
6687         {
6688                 r_refdef.lightmapintensity *= r_refdef.scene.worldmodel->lightmapscale;
6689         }
6690         if (r_showsurfaces.integer)
6691         {
6692                 r_refdef.scene.rtworld = false;
6693                 r_refdef.scene.rtworldshadows = false;
6694                 r_refdef.scene.rtdlight = false;
6695                 r_refdef.scene.rtdlightshadows = false;
6696                 r_refdef.lightmapintensity = 0;
6697         }
6698
6699         switch(vid.renderpath)
6700         {
6701         case RENDERPATH_GL20:
6702         case RENDERPATH_D3D9:
6703         case RENDERPATH_D3D10:
6704         case RENDERPATH_D3D11:
6705         case RENDERPATH_SOFT:
6706         case RENDERPATH_GLES2:
6707                 if(v_glslgamma.integer && !vid_gammatables_trivial)
6708                 {
6709                         if(!r_texture_gammaramps || vid_gammatables_serial != r_texture_gammaramps_serial)
6710                         {
6711                                 // build GLSL gamma texture
6712 #define RAMPWIDTH 256
6713                                 unsigned short ramp[RAMPWIDTH * 3];
6714                                 unsigned char rampbgr[RAMPWIDTH][4];
6715                                 int i;
6716
6717                                 r_texture_gammaramps_serial = vid_gammatables_serial;
6718
6719                                 VID_BuildGammaTables(&ramp[0], RAMPWIDTH);
6720                                 for(i = 0; i < RAMPWIDTH; ++i)
6721                                 {
6722                                         rampbgr[i][0] = (unsigned char) (ramp[i + 2 * RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6723                                         rampbgr[i][1] = (unsigned char) (ramp[i + RAMPWIDTH] * 255.0 / 65535.0 + 0.5);
6724                                         rampbgr[i][2] = (unsigned char) (ramp[i] * 255.0 / 65535.0 + 0.5);
6725                                         rampbgr[i][3] = 0;
6726                                 }
6727                                 if (r_texture_gammaramps)
6728                                 {
6729                                         R_UpdateTexture(r_texture_gammaramps, &rampbgr[0][0], 0, 0, 0, RAMPWIDTH, 1, 1);
6730                                 }
6731                                 else
6732                                 {
6733                                         r_texture_gammaramps = R_LoadTexture2D(r_main_texturepool, "gammaramps", RAMPWIDTH, 1, &rampbgr[0][0], TEXTYPE_BGRA, TEXF_FORCELINEAR | TEXF_CLAMP | TEXF_PERSISTENT, -1, NULL);
6734                                 }
6735                         }
6736                 }
6737                 else
6738                 {
6739                         // remove GLSL gamma texture
6740                 }
6741                 break;
6742         case RENDERPATH_GL11:
6743         case RENDERPATH_GL13:
6744         case RENDERPATH_GLES1:
6745                 break;
6746         }
6747 }
6748
6749 static r_refdef_scene_type_t r_currentscenetype = RST_CLIENT;
6750 static r_refdef_scene_t r_scenes_store[ RST_COUNT ];
6751 /*
6752 ================
6753 R_SelectScene
6754 ================
6755 */
6756 void R_SelectScene( r_refdef_scene_type_t scenetype ) {
6757         if( scenetype != r_currentscenetype ) {
6758                 // store the old scenetype
6759                 r_scenes_store[ r_currentscenetype ] = r_refdef.scene;
6760                 r_currentscenetype = scenetype;
6761                 // move in the new scene
6762                 r_refdef.scene = r_scenes_store[ r_currentscenetype ];
6763         }
6764 }
6765
6766 /*
6767 ================
6768 R_GetScenePointer
6769 ================
6770 */
6771 r_refdef_scene_t * R_GetScenePointer( r_refdef_scene_type_t scenetype )
6772 {
6773         // of course, we could also add a qboolean that provides a lock state and a ReleaseScenePointer function..
6774         if( scenetype == r_currentscenetype ) {
6775                 return &r_refdef.scene;
6776         } else {
6777                 return &r_scenes_store[ scenetype ];
6778         }
6779 }
6780
6781 static int R_SortEntities_Compare(const void *ap, const void *bp)
6782 {
6783         const entity_render_t *a = *(const entity_render_t **)ap;
6784         const entity_render_t *b = *(const entity_render_t **)bp;
6785
6786         // 1. compare model
6787         if(a->model < b->model)
6788                 return -1;
6789         if(a->model > b->model)
6790                 return +1;
6791
6792         // 2. compare skin
6793         // TODO possibly calculate the REAL skinnum here first using
6794         // skinscenes?
6795         if(a->skinnum < b->skinnum)
6796                 return -1;
6797         if(a->skinnum > b->skinnum)
6798                 return +1;
6799
6800         // everything we compared is equal
6801         return 0;
6802 }
6803 static void R_SortEntities(void)
6804 {
6805         // below or equal 2 ents, sorting never gains anything
6806         if(r_refdef.scene.numentities <= 2)
6807                 return;
6808         // sort
6809         qsort(r_refdef.scene.entities, r_refdef.scene.numentities, sizeof(*r_refdef.scene.entities), R_SortEntities_Compare);
6810 }
6811
6812 /*
6813 ================
6814 R_RenderView
6815 ================
6816 */
6817 int dpsoftrast_test;
6818 extern cvar_t r_shadow_bouncegrid;
6819 void R_RenderView(void)
6820 {
6821         matrix4x4_t originalmatrix = r_refdef.view.matrix, offsetmatrix;
6822         int fbo;
6823         rtexture_t *depthtexture;
6824         rtexture_t *colortexture;
6825
6826         dpsoftrast_test = r_test.integer;
6827
6828         if (r_timereport_active)
6829                 R_TimeReport("start");
6830         r_textureframe++; // used only by R_GetCurrentTexture
6831         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
6832
6833         if(R_CompileShader_CheckStaticParms())
6834                 R_GLSL_Restart_f();
6835
6836         if (!r_drawentities.integer)
6837                 r_refdef.scene.numentities = 0;
6838         else if (r_sortentities.integer)
6839                 R_SortEntities();
6840
6841         R_AnimCache_ClearCache();
6842         R_FrameData_NewFrame();
6843
6844         /* adjust for stereo display */
6845         if(R_Stereo_Active())
6846         {
6847                 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);
6848                 Matrix4x4_Concat(&r_refdef.view.matrix, &originalmatrix, &offsetmatrix);
6849         }
6850
6851         if (r_refdef.view.isoverlay)
6852         {
6853                 // TODO: FIXME: move this into its own backend function maybe? [2/5/2008 Andreas]
6854                 R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL);
6855                 GL_Clear(GL_DEPTH_BUFFER_BIT, NULL, 1.0f, 0);
6856                 R_TimeReport("depthclear");
6857
6858                 r_refdef.view.showdebug = false;
6859
6860                 r_fb.water.enabled = false;
6861                 r_fb.water.numwaterplanes = 0;
6862
6863                 R_RenderScene(0, NULL, NULL);
6864
6865                 r_refdef.view.matrix = originalmatrix;
6866
6867                 CHECKGLERROR
6868                 return;
6869         }
6870
6871         if (!r_refdef.scene.entities || r_refdef.view.width * r_refdef.view.height == 0 || !r_renderview.integer || cl_videoplaying/* || !r_refdef.scene.worldmodel*/)
6872         {
6873                 r_refdef.view.matrix = originalmatrix;
6874                 return;
6875         }
6876
6877         r_refdef.view.colorscale = r_hdr_scenebrightness.value * r_hdr_irisadaptation_value.value;
6878
6879         if(vid_sRGB.integer && vid_sRGB_fallback.integer && !vid.sRGB3D)
6880                 // in sRGB fallback, behave similar to true sRGB: convert this
6881                 // value from linear to sRGB
6882                 r_refdef.view.colorscale = Image_sRGBFloatFromLinearFloat(r_refdef.view.colorscale);
6883
6884         R_RenderView_UpdateViewVectors();
6885
6886         R_Shadow_UpdateWorldLightSelection();
6887
6888         R_Bloom_StartFrame();
6889         R_Water_StartFrame();
6890
6891         // now we probably have an fbo to render into
6892         fbo = r_fb.fbo;
6893         depthtexture = r_fb.depthtexture;
6894         colortexture = r_fb.colortexture;
6895
6896         CHECKGLERROR
6897         if (r_timereport_active)
6898                 R_TimeReport("viewsetup");
6899
6900         R_ResetViewRendering3D(fbo, depthtexture, colortexture);
6901
6902         if (r_refdef.view.clear || r_refdef.fogenabled || fbo)
6903         {
6904                 R_ClearScreen(r_refdef.fogenabled);
6905                 if (r_timereport_active)
6906                         R_TimeReport("viewclear");
6907         }
6908         r_refdef.view.clear = true;
6909
6910         r_refdef.view.showdebug = true;
6911
6912         R_View_Update();
6913         if (r_timereport_active)
6914                 R_TimeReport("visibility");
6915
6916         R_Shadow_UpdateBounceGridTexture();
6917         if (r_timereport_active && r_shadow_bouncegrid.integer)
6918                 R_TimeReport("bouncegrid");
6919
6920         r_fb.water.numwaterplanes = 0;
6921         if (r_fb.water.enabled)
6922                 R_RenderWaterPlanes(fbo, depthtexture, colortexture);
6923
6924         R_RenderScene(fbo, depthtexture, colortexture);
6925         r_fb.water.numwaterplanes = 0;
6926
6927         R_BlendView(fbo, depthtexture, colortexture);
6928         if (r_timereport_active)
6929                 R_TimeReport("blendview");
6930
6931         GL_Scissor(0, 0, vid.width, vid.height);
6932         GL_ScissorTest(false);
6933
6934         r_refdef.view.matrix = originalmatrix;
6935
6936         CHECKGLERROR
6937 }
6938
6939 void R_RenderWaterPlanes(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6940 {
6941         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawAddWaterPlanes)
6942         {
6943                 r_refdef.scene.worldmodel->DrawAddWaterPlanes(r_refdef.scene.worldentity);
6944                 if (r_timereport_active)
6945                         R_TimeReport("waterworld");
6946         }
6947
6948         // don't let sound skip if going slow
6949         if (r_refdef.scene.extraupdate)
6950                 S_ExtraUpdate ();
6951
6952         R_DrawModelsAddWaterPlanes();
6953         if (r_timereport_active)
6954                 R_TimeReport("watermodels");
6955
6956         if (r_fb.water.numwaterplanes)
6957         {
6958                 R_Water_ProcessPlanes(fbo, depthtexture, colortexture);
6959                 if (r_timereport_active)
6960                         R_TimeReport("waterscenes");
6961         }
6962 }
6963
6964 extern cvar_t cl_locs_show;
6965 static void R_DrawLocs(void);
6966 static void R_DrawEntityBBoxes(void);
6967 static void R_DrawModelDecals(void);
6968 extern cvar_t cl_decals_newsystem;
6969 extern qboolean r_shadow_usingdeferredprepass;
6970 void R_RenderScene(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture)
6971 {
6972         qboolean shadowmapping = false;
6973
6974         if (r_timereport_active)
6975                 R_TimeReport("beginscene");
6976
6977         r_refdef.stats.renders++;
6978
6979         R_UpdateFog();
6980
6981         // don't let sound skip if going slow
6982         if (r_refdef.scene.extraupdate)
6983                 S_ExtraUpdate ();
6984
6985         R_MeshQueue_BeginScene();
6986
6987         R_SkyStartFrame();
6988
6989         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);
6990
6991         if (r_timereport_active)
6992                 R_TimeReport("skystartframe");
6993
6994         if (cl.csqc_vidvars.drawworld)
6995         {
6996                 // don't let sound skip if going slow
6997                 if (r_refdef.scene.extraupdate)
6998                         S_ExtraUpdate ();
6999
7000                 if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawSky)
7001                 {
7002                         r_refdef.scene.worldmodel->DrawSky(r_refdef.scene.worldentity);
7003                         if (r_timereport_active)
7004                                 R_TimeReport("worldsky");
7005                 }
7006
7007                 if (R_DrawBrushModelsSky() && r_timereport_active)
7008                         R_TimeReport("bmodelsky");
7009
7010                 if (skyrendermasked && skyrenderlater)
7011                 {
7012                         // we have to force off the water clipping plane while rendering sky
7013                         R_SetupView(false, fbo, depthtexture, colortexture);
7014                         R_Sky();
7015                         R_SetupView(true, fbo, depthtexture, colortexture);
7016                         if (r_timereport_active)
7017                                 R_TimeReport("sky");
7018                 }
7019         }
7020
7021         R_Shadow_PrepareLights(fbo, depthtexture, colortexture);
7022         if (r_shadows.integer > 0 && r_refdef.lightmapintensity > 0)
7023                 R_Shadow_PrepareModelShadows();
7024         if (r_timereport_active)
7025                 R_TimeReport("preparelights");
7026
7027         if (R_Shadow_ShadowMappingEnabled())
7028                 shadowmapping = true;
7029
7030         if (r_shadow_usingdeferredprepass)
7031                 R_Shadow_DrawPrepass();
7032
7033         if (r_depthfirst.integer >= 1 && cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->DrawDepth)
7034         {
7035                 r_refdef.scene.worldmodel->DrawDepth(r_refdef.scene.worldentity);
7036                 if (r_timereport_active)
7037                         R_TimeReport("worlddepth");
7038         }
7039         if (r_depthfirst.integer >= 2)
7040         {
7041                 R_DrawModelsDepth();
7042                 if (r_timereport_active)
7043                         R_TimeReport("modeldepth");
7044         }
7045
7046         if (r_shadows.integer >= 2 && shadowmapping && r_refdef.lightmapintensity > 0)
7047         {
7048                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7049                 R_DrawModelShadowMaps(fbo, depthtexture, colortexture);
7050                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7051                 // don't let sound skip if going slow
7052                 if (r_refdef.scene.extraupdate)
7053                         S_ExtraUpdate ();
7054         }
7055
7056         if (cl.csqc_vidvars.drawworld && r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->Draw)
7057         {
7058                 r_refdef.scene.worldmodel->Draw(r_refdef.scene.worldentity);
7059                 if (r_timereport_active)
7060                         R_TimeReport("world");
7061         }
7062
7063         // don't let sound skip if going slow
7064         if (r_refdef.scene.extraupdate)
7065                 S_ExtraUpdate ();
7066
7067         R_DrawModels();
7068         if (r_timereport_active)
7069                 R_TimeReport("models");
7070
7071         // don't let sound skip if going slow
7072         if (r_refdef.scene.extraupdate)
7073                 S_ExtraUpdate ();
7074
7075         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && !r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7076         {
7077                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7078                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7079                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7080                 // don't let sound skip if going slow
7081                 if (r_refdef.scene.extraupdate)
7082                         S_ExtraUpdate ();
7083         }
7084
7085         if (!r_shadow_usingdeferredprepass)
7086         {
7087                 R_Shadow_DrawLights();
7088                 if (r_timereport_active)
7089                         R_TimeReport("rtlights");
7090         }
7091
7092         // don't let sound skip if going slow
7093         if (r_refdef.scene.extraupdate)
7094                 S_ExtraUpdate ();
7095
7096         if ((r_shadows.integer == 1 || (r_shadows.integer > 0 && !shadowmapping)) && r_shadows_drawafterrtlighting.integer && r_refdef.lightmapintensity > 0)
7097         {
7098                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7099                 R_DrawModelShadows(fbo, depthtexture, colortexture);
7100                 R_ResetViewRendering3D(fbo, depthtexture, colortexture);
7101                 // don't let sound skip if going slow
7102                 if (r_refdef.scene.extraupdate)
7103                         S_ExtraUpdate ();
7104         }
7105
7106         if (cl.csqc_vidvars.drawworld)
7107         {
7108                 if (cl_decals_newsystem.integer)
7109                 {
7110                         R_DrawModelDecals();
7111                         if (r_timereport_active)
7112                                 R_TimeReport("modeldecals");
7113                 }
7114                 else
7115                 {
7116                         R_DrawDecals();
7117                         if (r_timereport_active)
7118                                 R_TimeReport("decals");
7119                 }
7120
7121                 R_DrawParticles();
7122                 if (r_timereport_active)
7123                         R_TimeReport("particles");
7124
7125                 R_DrawExplosions();
7126                 if (r_timereport_active)
7127                         R_TimeReport("explosions");
7128
7129                 R_DrawLightningBeams();
7130                 if (r_timereport_active)
7131                         R_TimeReport("lightning");
7132         }
7133
7134         if (cl.csqc_loaded)
7135                 VM_CL_AddPolygonsToMeshQueue(CLVM_prog);
7136
7137         if (r_refdef.view.showdebug)
7138         {
7139                 if (cl_locs_show.integer)
7140                 {
7141                         R_DrawLocs();
7142                         if (r_timereport_active)
7143                                 R_TimeReport("showlocs");
7144                 }
7145
7146                 if (r_drawportals.integer)
7147                 {
7148                         R_DrawPortals();
7149                         if (r_timereport_active)
7150                                 R_TimeReport("portals");
7151                 }
7152
7153                 if (r_showbboxes.value > 0)
7154                 {
7155                         R_DrawEntityBBoxes();
7156                         if (r_timereport_active)
7157                                 R_TimeReport("bboxes");
7158                 }
7159         }
7160
7161         if (r_transparent.integer)
7162         {
7163                 R_MeshQueue_RenderTransparent();
7164                 if (r_timereport_active)
7165                         R_TimeReport("drawtrans");
7166         }
7167
7168         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))
7169         {
7170                 r_refdef.scene.worldmodel->DrawDebug(r_refdef.scene.worldentity);
7171                 if (r_timereport_active)
7172                         R_TimeReport("worlddebug");
7173                 R_DrawModelsDebug();
7174                 if (r_timereport_active)
7175                         R_TimeReport("modeldebug");
7176         }
7177
7178         if (cl.csqc_vidvars.drawworld)
7179         {
7180                 R_Shadow_DrawCoronas();
7181                 if (r_timereport_active)
7182                         R_TimeReport("coronas");
7183         }
7184
7185 #if 0
7186         {
7187                 GL_DepthTest(false);
7188                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
7189                 GL_Color(1, 1, 1, 1);
7190                 qglBegin(GL_POLYGON);
7191                 qglVertex3f(r_refdef.view.frustumcorner[0][0], r_refdef.view.frustumcorner[0][1], r_refdef.view.frustumcorner[0][2]);
7192                 qglVertex3f(r_refdef.view.frustumcorner[1][0], r_refdef.view.frustumcorner[1][1], r_refdef.view.frustumcorner[1][2]);
7193                 qglVertex3f(r_refdef.view.frustumcorner[3][0], r_refdef.view.frustumcorner[3][1], r_refdef.view.frustumcorner[3][2]);
7194                 qglVertex3f(r_refdef.view.frustumcorner[2][0], r_refdef.view.frustumcorner[2][1], r_refdef.view.frustumcorner[2][2]);
7195                 qglEnd();
7196                 qglBegin(GL_POLYGON);
7197                 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]);
7198                 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]);
7199                 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]);
7200                 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]);
7201                 qglEnd();
7202                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
7203         }
7204 #endif
7205
7206         // don't let sound skip if going slow
7207         if (r_refdef.scene.extraupdate)
7208                 S_ExtraUpdate ();
7209 }
7210
7211 static const unsigned short bboxelements[36] =
7212 {
7213         5, 1, 3, 5, 3, 7,
7214         6, 2, 0, 6, 0, 4,
7215         7, 3, 2, 7, 2, 6,
7216         4, 0, 1, 4, 1, 5,
7217         4, 5, 7, 4, 7, 6,
7218         1, 0, 2, 1, 2, 3,
7219 };
7220
7221 static void R_DrawBBoxMesh(vec3_t mins, vec3_t maxs, float cr, float cg, float cb, float ca)
7222 {
7223         int i;
7224         float *v, *c, f1, f2, vertex3f[8*3], color4f[8*4];
7225
7226         RSurf_ActiveWorldEntity();
7227
7228         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7229         GL_DepthMask(false);
7230         GL_DepthRange(0, 1);
7231         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
7232 //      R_Mesh_ResetTextureState();
7233
7234         vertex3f[ 0] = mins[0];vertex3f[ 1] = mins[1];vertex3f[ 2] = mins[2]; //
7235         vertex3f[ 3] = maxs[0];vertex3f[ 4] = mins[1];vertex3f[ 5] = mins[2];
7236         vertex3f[ 6] = mins[0];vertex3f[ 7] = maxs[1];vertex3f[ 8] = mins[2];
7237         vertex3f[ 9] = maxs[0];vertex3f[10] = maxs[1];vertex3f[11] = mins[2];
7238         vertex3f[12] = mins[0];vertex3f[13] = mins[1];vertex3f[14] = maxs[2];
7239         vertex3f[15] = maxs[0];vertex3f[16] = mins[1];vertex3f[17] = maxs[2];
7240         vertex3f[18] = mins[0];vertex3f[19] = maxs[1];vertex3f[20] = maxs[2];
7241         vertex3f[21] = maxs[0];vertex3f[22] = maxs[1];vertex3f[23] = maxs[2];
7242         R_FillColors(color4f, 8, cr, cg, cb, ca);
7243         if (r_refdef.fogenabled)
7244         {
7245                 for (i = 0, v = vertex3f, c = color4f;i < 8;i++, v += 3, c += 4)
7246                 {
7247                         f1 = RSurf_FogVertex(v);
7248                         f2 = 1 - f1;
7249                         c[0] = c[0] * f1 + r_refdef.fogcolor[0] * f2;
7250                         c[1] = c[1] * f1 + r_refdef.fogcolor[1] * f2;
7251                         c[2] = c[2] * f1 + r_refdef.fogcolor[2] * f2;
7252                 }
7253         }
7254         R_Mesh_PrepareVertices_Generic_Arrays(8, vertex3f, color4f, NULL);
7255         R_Mesh_ResetTextureState();
7256         R_SetupShader_Generic_NoTexture(false, false);
7257         R_Mesh_Draw(0, 8, 0, 12, NULL, NULL, 0, bboxelements, NULL, 0);
7258 }
7259
7260 static void R_DrawEntityBBoxes_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7261 {
7262         prvm_prog_t *prog = SVVM_prog;
7263         int i;
7264         float color[4];
7265         prvm_edict_t *edict;
7266
7267         // this function draws bounding boxes of server entities
7268         if (!sv.active)
7269                 return;
7270
7271         GL_CullFace(GL_NONE);
7272         R_SetupShader_Generic_NoTexture(false, false);
7273
7274         for (i = 0;i < numsurfaces;i++)
7275         {
7276                 edict = PRVM_EDICT_NUM(surfacelist[i]);
7277                 switch ((int)PRVM_serveredictfloat(edict, solid))
7278                 {
7279                         case SOLID_NOT:      Vector4Set(color, 1, 1, 1, 0.05);break;
7280                         case SOLID_TRIGGER:  Vector4Set(color, 1, 0, 1, 0.10);break;
7281                         case SOLID_BBOX:     Vector4Set(color, 0, 1, 0, 0.10);break;
7282                         case SOLID_SLIDEBOX: Vector4Set(color, 1, 0, 0, 0.10);break;
7283                         case SOLID_BSP:      Vector4Set(color, 0, 0, 1, 0.05);break;
7284                         case SOLID_CORPSE:   Vector4Set(color, 1, 0.5, 0, 0.05);break;
7285                         default:             Vector4Set(color, 0, 0, 0, 0.50);break;
7286                 }
7287                 color[3] *= r_showbboxes.value;
7288                 color[3] = bound(0, color[3], 1);
7289                 GL_DepthTest(!r_showdisabledepthtest.integer);
7290                 GL_CullFace(r_refdef.view.cullface_front);
7291                 R_DrawBBoxMesh(edict->priv.server->areamins, edict->priv.server->areamaxs, color[0], color[1], color[2], color[3]);
7292         }
7293 }
7294
7295 static void R_DrawEntityBBoxes(void)
7296 {
7297         int i;
7298         prvm_edict_t *edict;
7299         vec3_t center;
7300         prvm_prog_t *prog = SVVM_prog;
7301
7302         // this function draws bounding boxes of server entities
7303         if (!sv.active)
7304                 return;
7305
7306         for (i = 0;i < prog->num_edicts;i++)
7307         {
7308                 edict = PRVM_EDICT_NUM(i);
7309                 if (edict->priv.server->free)
7310                         continue;
7311                 // exclude the following for now, as they don't live in world coordinate space and can't be solid:
7312                 if(PRVM_serveredictedict(edict, tag_entity) != 0)
7313                         continue;
7314                 if(PRVM_serveredictedict(edict, viewmodelforclient) != 0)
7315                         continue;
7316                 VectorLerp(edict->priv.server->areamins, 0.5f, edict->priv.server->areamaxs, center);
7317                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawEntityBBoxes_Callback, (entity_render_t *)NULL, i, (rtlight_t *)NULL);
7318         }
7319 }
7320
7321 static const int nomodelelement3i[24] =
7322 {
7323         5, 2, 0,
7324         5, 1, 2,
7325         5, 0, 3,
7326         5, 3, 1,
7327         0, 2, 4,
7328         2, 1, 4,
7329         3, 0, 4,
7330         1, 3, 4
7331 };
7332
7333 static const unsigned short nomodelelement3s[24] =
7334 {
7335         5, 2, 0,
7336         5, 1, 2,
7337         5, 0, 3,
7338         5, 3, 1,
7339         0, 2, 4,
7340         2, 1, 4,
7341         3, 0, 4,
7342         1, 3, 4
7343 };
7344
7345 static const float nomodelvertex3f[6*3] =
7346 {
7347         -16,   0,   0,
7348          16,   0,   0,
7349           0, -16,   0,
7350           0,  16,   0,
7351           0,   0, -16,
7352           0,   0,  16
7353 };
7354
7355 static const float nomodelcolor4f[6*4] =
7356 {
7357         0.0f, 0.0f, 0.5f, 1.0f,
7358         0.0f, 0.0f, 0.5f, 1.0f,
7359         0.0f, 0.5f, 0.0f, 1.0f,
7360         0.0f, 0.5f, 0.0f, 1.0f,
7361         0.5f, 0.0f, 0.0f, 1.0f,
7362         0.5f, 0.0f, 0.0f, 1.0f
7363 };
7364
7365 static void R_DrawNoModel_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
7366 {
7367         int i;
7368         float f1, f2, *c;
7369         float color4f[6*4];
7370
7371         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);
7372
7373         // this is only called once per entity so numsurfaces is always 1, and
7374         // surfacelist is always {0}, so this code does not handle batches
7375
7376         if (rsurface.ent_flags & RENDER_ADDITIVE)
7377         {
7378                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE);
7379                 GL_DepthMask(false);
7380         }
7381         else if (rsurface.colormod[3] < 1)
7382         {
7383                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
7384                 GL_DepthMask(false);
7385         }
7386         else
7387         {
7388                 GL_BlendFunc(GL_ONE, GL_ZERO);
7389                 GL_DepthMask(true);
7390         }
7391         GL_DepthRange(0, (rsurface.ent_flags & RENDER_VIEWMODEL) ? 0.0625 : 1);
7392         GL_PolygonOffset(rsurface.basepolygonfactor, rsurface.basepolygonoffset);
7393         GL_DepthTest(!(rsurface.ent_flags & RENDER_NODEPTHTEST));
7394         GL_CullFace((rsurface.ent_flags & RENDER_DOUBLESIDED) ? GL_NONE : r_refdef.view.cullface_back);
7395         memcpy(color4f, nomodelcolor4f, sizeof(float[6*4]));
7396         for (i = 0, c = color4f;i < 6;i++, c += 4)
7397         {
7398                 c[0] *= rsurface.colormod[0];
7399                 c[1] *= rsurface.colormod[1];
7400                 c[2] *= rsurface.colormod[2];
7401                 c[3] *= rsurface.colormod[3];
7402         }
7403         if (r_refdef.fogenabled)
7404         {
7405                 for (i = 0, c = color4f;i < 6;i++, c += 4)
7406                 {
7407                         f1 = RSurf_FogVertex(nomodelvertex3f + 3*i);
7408                         f2 = 1 - f1;
7409                         c[0] = (c[0] * f1 + r_refdef.fogcolor[0] * f2);
7410                         c[1] = (c[1] * f1 + r_refdef.fogcolor[1] * f2);
7411                         c[2] = (c[2] * f1 + r_refdef.fogcolor[2] * f2);
7412                 }
7413         }
7414 //      R_Mesh_ResetTextureState();
7415         R_SetupShader_Generic_NoTexture(false, false);
7416         R_Mesh_PrepareVertices_Generic_Arrays(6, nomodelvertex3f, color4f, NULL);
7417         R_Mesh_Draw(0, 6, 0, 8, nomodelelement3i, NULL, 0, nomodelelement3s, NULL, 0);
7418 }
7419
7420 void R_DrawNoModel(entity_render_t *ent)
7421 {
7422         vec3_t org;
7423         Matrix4x4_OriginFromMatrix(&ent->matrix, org);
7424         if ((ent->flags & RENDER_ADDITIVE) || (ent->alpha < 1))
7425                 R_MeshQueue_AddTransparent((ent->flags & RENDER_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : MESHQUEUE_SORT_DISTANCE, org, R_DrawNoModel_TransparentCallback, ent, 0, rsurface.rtlight);
7426         else
7427                 R_DrawNoModel_TransparentCallback(ent, rsurface.rtlight, 0, NULL);
7428 }
7429
7430 void R_CalcBeam_Vertex3f (float *vert, const vec3_t org1, const vec3_t org2, float width)
7431 {
7432         vec3_t right1, right2, diff, normal;
7433
7434         VectorSubtract (org2, org1, normal);
7435
7436         // calculate 'right' vector for start
7437         VectorSubtract (r_refdef.view.origin, org1, diff);
7438         CrossProduct (normal, diff, right1);
7439         VectorNormalize (right1);
7440
7441         // calculate 'right' vector for end
7442         VectorSubtract (r_refdef.view.origin, org2, diff);
7443         CrossProduct (normal, diff, right2);
7444         VectorNormalize (right2);
7445
7446         vert[ 0] = org1[0] + width * right1[0];
7447         vert[ 1] = org1[1] + width * right1[1];
7448         vert[ 2] = org1[2] + width * right1[2];
7449         vert[ 3] = org1[0] - width * right1[0];
7450         vert[ 4] = org1[1] - width * right1[1];
7451         vert[ 5] = org1[2] - width * right1[2];
7452         vert[ 6] = org2[0] - width * right2[0];
7453         vert[ 7] = org2[1] - width * right2[1];
7454         vert[ 8] = org2[2] - width * right2[2];
7455         vert[ 9] = org2[0] + width * right2[0];
7456         vert[10] = org2[1] + width * right2[1];
7457         vert[11] = org2[2] + width * right2[2];
7458 }
7459
7460 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)
7461 {
7462         vertex3f[ 0] = origin[0] + left[0] * scalex2 + up[0] * scaley1;
7463         vertex3f[ 1] = origin[1] + left[1] * scalex2 + up[1] * scaley1;
7464         vertex3f[ 2] = origin[2] + left[2] * scalex2 + up[2] * scaley1;
7465         vertex3f[ 3] = origin[0] + left[0] * scalex2 + up[0] * scaley2;
7466         vertex3f[ 4] = origin[1] + left[1] * scalex2 + up[1] * scaley2;
7467         vertex3f[ 5] = origin[2] + left[2] * scalex2 + up[2] * scaley2;
7468         vertex3f[ 6] = origin[0] + left[0] * scalex1 + up[0] * scaley2;
7469         vertex3f[ 7] = origin[1] + left[1] * scalex1 + up[1] * scaley2;
7470         vertex3f[ 8] = origin[2] + left[2] * scalex1 + up[2] * scaley2;
7471         vertex3f[ 9] = origin[0] + left[0] * scalex1 + up[0] * scaley1;
7472         vertex3f[10] = origin[1] + left[1] * scalex1 + up[1] * scaley1;
7473         vertex3f[11] = origin[2] + left[2] * scalex1 + up[2] * scaley1;
7474 }
7475
7476 static int R_Mesh_AddVertex(rmesh_t *mesh, float x, float y, float z)
7477 {
7478         int i;
7479         float *vertex3f;
7480         float v[3];
7481         VectorSet(v, x, y, z);
7482         for (i = 0, vertex3f = mesh->vertex3f;i < mesh->numvertices;i++, vertex3f += 3)
7483                 if (VectorDistance2(v, vertex3f) < mesh->epsilon2)
7484                         break;
7485         if (i == mesh->numvertices)
7486         {
7487                 if (mesh->numvertices < mesh->maxvertices)
7488                 {
7489                         VectorCopy(v, vertex3f);
7490                         mesh->numvertices++;
7491                 }
7492                 return mesh->numvertices;
7493         }
7494         else
7495                 return i;
7496 }
7497
7498 void R_Mesh_AddPolygon3f(rmesh_t *mesh, int numvertices, float *vertex3f)
7499 {
7500         int i;
7501         int *e, element[3];
7502         element[0] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7503         element[1] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);vertex3f += 3;
7504         e = mesh->element3i + mesh->numtriangles * 3;
7505         for (i = 0;i < numvertices - 2;i++, vertex3f += 3)
7506         {
7507                 element[2] = R_Mesh_AddVertex(mesh, vertex3f[0], vertex3f[1], vertex3f[2]);
7508                 if (mesh->numtriangles < mesh->maxtriangles)
7509                 {
7510                         *e++ = element[0];
7511                         *e++ = element[1];
7512                         *e++ = element[2];
7513                         mesh->numtriangles++;
7514                 }
7515                 element[1] = element[2];
7516         }
7517 }
7518
7519 static void R_Mesh_AddPolygon3d(rmesh_t *mesh, int numvertices, double *vertex3d)
7520 {
7521         int i;
7522         int *e, element[3];
7523         element[0] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7524         element[1] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);vertex3d += 3;
7525         e = mesh->element3i + mesh->numtriangles * 3;
7526         for (i = 0;i < numvertices - 2;i++, vertex3d += 3)
7527         {
7528                 element[2] = R_Mesh_AddVertex(mesh, vertex3d[0], vertex3d[1], vertex3d[2]);
7529                 if (mesh->numtriangles < mesh->maxtriangles)
7530                 {
7531                         *e++ = element[0];
7532                         *e++ = element[1];
7533                         *e++ = element[2];
7534                         mesh->numtriangles++;
7535                 }
7536                 element[1] = element[2];
7537         }
7538 }
7539
7540 #define R_MESH_PLANE_DIST_EPSILON (1.0 / 32.0)
7541 void R_Mesh_AddBrushMeshFromPlanes(rmesh_t *mesh, int numplanes, mplane_t *planes)
7542 {
7543         int planenum, planenum2;
7544         int w;
7545         int tempnumpoints;
7546         mplane_t *plane, *plane2;
7547         double maxdist;
7548         double temppoints[2][256*3];
7549         // figure out how large a bounding box we need to properly compute this brush
7550         maxdist = 0;
7551         for (w = 0;w < numplanes;w++)
7552                 maxdist = max(maxdist, fabs(planes[w].dist));
7553         // now make it large enough to enclose the entire brush, and round it off to a reasonable multiple of 1024
7554         maxdist = floor(maxdist * (4.0 / 1024.0) + 1) * 1024.0;
7555         for (planenum = 0, plane = planes;planenum < numplanes;planenum++, plane++)
7556         {
7557                 w = 0;
7558                 tempnumpoints = 4;
7559                 PolygonD_QuadForPlane(temppoints[w], plane->normal[0], plane->normal[1], plane->normal[2], plane->dist, maxdist);
7560                 for (planenum2 = 0, plane2 = planes;planenum2 < numplanes && tempnumpoints >= 3;planenum2++, plane2++)
7561                 {
7562                         if (planenum2 == planenum)
7563                                 continue;
7564                         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);
7565                         w = !w;
7566                 }
7567                 if (tempnumpoints < 3)
7568                         continue;
7569                 // generate elements forming a triangle fan for this polygon
7570                 R_Mesh_AddPolygon3d(mesh, tempnumpoints, temppoints[w]);
7571         }
7572 }
7573
7574 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)
7575 {
7576         texturelayer_t *layer;
7577         layer = t->currentlayers + t->currentnumlayers++;
7578         layer->type = type;
7579         layer->depthmask = depthmask;
7580         layer->blendfunc1 = blendfunc1;
7581         layer->blendfunc2 = blendfunc2;
7582         layer->texture = texture;
7583         layer->texmatrix = *matrix;
7584         layer->color[0] = r;
7585         layer->color[1] = g;
7586         layer->color[2] = b;
7587         layer->color[3] = a;
7588 }
7589
7590 static qboolean R_TestQ3WaveFunc(q3wavefunc_t func, const float *parms)
7591 {
7592         if(parms[0] == 0 && parms[1] == 0)
7593                 return false;
7594         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7595                 if(rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)] == 0)
7596                         return false;
7597         return true;
7598 }
7599
7600 static float R_EvaluateQ3WaveFunc(q3wavefunc_t func, const float *parms)
7601 {
7602         double index, f;
7603         index = parms[2] + rsurface.shadertime * parms[3];
7604         index -= floor(index);
7605         switch (func & ((1 << Q3WAVEFUNC_USER_SHIFT) - 1))
7606         {
7607         default:
7608         case Q3WAVEFUNC_NONE:
7609         case Q3WAVEFUNC_NOISE:
7610         case Q3WAVEFUNC_COUNT:
7611                 f = 0;
7612                 break;
7613         case Q3WAVEFUNC_SIN: f = sin(index * M_PI * 2);break;
7614         case Q3WAVEFUNC_SQUARE: f = index < 0.5 ? 1 : -1;break;
7615         case Q3WAVEFUNC_SAWTOOTH: f = index;break;
7616         case Q3WAVEFUNC_INVERSESAWTOOTH: f = 1 - index;break;
7617         case Q3WAVEFUNC_TRIANGLE:
7618                 index *= 4;
7619                 f = index - floor(index);
7620                 if (index < 1)
7621                 {
7622                         // f = f;
7623                 }
7624                 else if (index < 2)
7625                         f = 1 - f;
7626                 else if (index < 3)
7627                         f = -f;
7628                 else
7629                         f = -(1 - f);
7630                 break;
7631         }
7632         f = parms[0] + parms[1] * f;
7633         if(func >> Q3WAVEFUNC_USER_SHIFT) // assumes rsurface to be set!
7634                 f *= rsurface.userwavefunc_param[bound(0, (func >> Q3WAVEFUNC_USER_SHIFT) - 1, Q3WAVEFUNC_USER_COUNT - 1)];
7635         return (float) f;
7636 }
7637
7638 static void R_tcMod_ApplyToMatrix(matrix4x4_t *texmatrix, q3shaderinfo_layer_tcmod_t *tcmod, int currentmaterialflags)
7639 {
7640         int w, h, idx;
7641         double f;
7642         double offsetd[2];
7643         float tcmat[12];
7644         matrix4x4_t matrix, temp;
7645         switch(tcmod->tcmod)
7646         {
7647                 case Q3TCMOD_COUNT:
7648                 case Q3TCMOD_NONE:
7649                         if (currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7650                                 matrix = r_waterscrollmatrix;
7651                         else
7652                                 matrix = identitymatrix;
7653                         break;
7654                 case Q3TCMOD_ENTITYTRANSLATE:
7655                         // this is used in Q3 to allow the gamecode to control texcoord
7656                         // scrolling on the entity, which is not supported in darkplaces yet.
7657                         Matrix4x4_CreateTranslate(&matrix, 0, 0, 0);
7658                         break;
7659                 case Q3TCMOD_ROTATE:
7660                         f = tcmod->parms[0] * rsurface.shadertime;
7661                         Matrix4x4_CreateTranslate(&matrix, 0.5, 0.5, 0);
7662                         Matrix4x4_ConcatRotate(&matrix, (f / 360 - floor(f / 360)) * 360, 0, 0, 1);
7663                         Matrix4x4_ConcatTranslate(&matrix, -0.5, -0.5, 0);
7664                         break;
7665                 case Q3TCMOD_SCALE:
7666                         Matrix4x4_CreateScale3(&matrix, tcmod->parms[0], tcmod->parms[1], 1);
7667                         break;
7668                 case Q3TCMOD_SCROLL:
7669                         // extra care is needed because of precision breakdown with large values of time
7670                         offsetd[0] = tcmod->parms[0] * rsurface.shadertime;
7671                         offsetd[1] = tcmod->parms[1] * rsurface.shadertime;
7672                         Matrix4x4_CreateTranslate(&matrix, offsetd[0] - floor(offsetd[0]), offsetd[1] - floor(offsetd[1]), 0);
7673                         break;
7674                 case Q3TCMOD_PAGE: // poor man's animmap (to store animations into a single file, useful for HTTP downloaded textures)
7675                         w = (int) tcmod->parms[0];
7676                         h = (int) tcmod->parms[1];
7677                         f = rsurface.shadertime / (tcmod->parms[2] * w * h);
7678                         f = f - floor(f);
7679                         idx = (int) floor(f * w * h);
7680                         Matrix4x4_CreateTranslate(&matrix, (idx % w) / tcmod->parms[0], (idx / w) / tcmod->parms[1], 0);
7681                         break;
7682                 case Q3TCMOD_STRETCH:
7683                         f = 1.0f / R_EvaluateQ3WaveFunc(tcmod->wavefunc, tcmod->waveparms);
7684                         Matrix4x4_CreateFromQuakeEntity(&matrix, 0.5f * (1 - f), 0.5 * (1 - f), 0, 0, 0, 0, f);
7685                         break;
7686                 case Q3TCMOD_TRANSFORM:
7687                         VectorSet(tcmat +  0, tcmod->parms[0], tcmod->parms[1], 0);
7688                         VectorSet(tcmat +  3, tcmod->parms[2], tcmod->parms[3], 0);
7689                         VectorSet(tcmat +  6, 0                   , 0                , 1);
7690                         VectorSet(tcmat +  9, tcmod->parms[4], tcmod->parms[5], 0);
7691                         Matrix4x4_FromArray12FloatGL(&matrix, tcmat);
7692                         break;
7693                 case Q3TCMOD_TURBULENT:
7694                         // this is handled in the RSurf_PrepareVertices function
7695                         matrix = identitymatrix;
7696                         break;
7697         }
7698         temp = *texmatrix;
7699         Matrix4x4_Concat(texmatrix, &matrix, &temp);
7700 }
7701
7702 static void R_LoadQWSkin(r_qwskincache_t *cache, const char *skinname)
7703 {
7704         int textureflags = (r_mipskins.integer ? TEXF_MIPMAP : 0) | TEXF_PICMIP;
7705         char name[MAX_QPATH];
7706         skinframe_t *skinframe;
7707         unsigned char pixels[296*194];
7708         strlcpy(cache->name, skinname, sizeof(cache->name));
7709         dpsnprintf(name, sizeof(name), "skins/%s.pcx", cache->name);
7710         if (developer_loading.integer)
7711                 Con_Printf("loading %s\n", name);
7712         skinframe = R_SkinFrame_Find(name, textureflags, 0, 0, 0, false);
7713         if (!skinframe || !skinframe->base)
7714         {
7715                 unsigned char *f;
7716                 fs_offset_t filesize;
7717                 skinframe = NULL;
7718                 f = FS_LoadFile(name, tempmempool, true, &filesize);
7719                 if (f)
7720                 {
7721                         if (LoadPCX_QWSkin(f, (int)filesize, pixels, 296, 194))
7722                                 skinframe = R_SkinFrame_LoadInternalQuake(name, textureflags, true, r_fullbrights.integer, pixels, image_width, image_height);
7723                         Mem_Free(f);
7724                 }
7725         }
7726         cache->skinframe = skinframe;
7727 }
7728
7729 texture_t *R_GetCurrentTexture(texture_t *t)
7730 {
7731         int i;
7732         const entity_render_t *ent = rsurface.entity;
7733         dp_model_t *model = ent->model;
7734         q3shaderinfo_layer_tcmod_t *tcmod;
7735
7736         if (t->update_lastrenderframe == r_textureframe && t->update_lastrenderentity == (void *)ent)
7737                 return t->currentframe;
7738         t->update_lastrenderframe = r_textureframe;
7739         t->update_lastrenderentity = (void *)ent;
7740
7741         if(ent && ent->entitynumber >= MAX_EDICTS && ent->entitynumber < 2 * MAX_EDICTS)
7742                 t->camera_entity = ent->entitynumber;
7743         else
7744                 t->camera_entity = 0;
7745
7746         // switch to an alternate material if this is a q1bsp animated material
7747         {
7748                 texture_t *texture = t;
7749                 int s = rsurface.ent_skinnum;
7750                 if ((unsigned int)s >= (unsigned int)model->numskins)
7751                         s = 0;
7752                 if (model->skinscenes)
7753                 {
7754                         if (model->skinscenes[s].framecount > 1)
7755                                 s = model->skinscenes[s].firstframe + (unsigned int) (rsurface.shadertime * model->skinscenes[s].framerate) % model->skinscenes[s].framecount;
7756                         else
7757                                 s = model->skinscenes[s].firstframe;
7758                 }
7759                 if (s > 0)
7760                         t = t + s * model->num_surfaces;
7761                 if (t->animated)
7762                 {
7763                         // use an alternate animation if the entity's frame is not 0,
7764                         // and only if the texture has an alternate animation
7765                         if (rsurface.ent_alttextures && t->anim_total[1])
7766                                 t = t->anim_frames[1][(t->anim_total[1] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[1]) : 0];
7767                         else
7768                                 t = t->anim_frames[0][(t->anim_total[0] >= 2) ? ((int)(rsurface.shadertime * 5.0f) % t->anim_total[0]) : 0];
7769                 }
7770                 texture->currentframe = t;
7771         }
7772
7773         // update currentskinframe to be a qw skin or animation frame
7774         if (rsurface.ent_qwskin >= 0)
7775         {
7776                 i = rsurface.ent_qwskin;
7777                 if (!r_qwskincache || r_qwskincache_size != cl.maxclients)
7778                 {
7779                         r_qwskincache_size = cl.maxclients;
7780                         if (r_qwskincache)
7781                                 Mem_Free(r_qwskincache);
7782                         r_qwskincache = (r_qwskincache_t *)Mem_Alloc(r_main_mempool, sizeof(*r_qwskincache) * r_qwskincache_size);
7783                 }
7784                 if (strcmp(r_qwskincache[i].name, cl.scores[i].qw_skin))
7785                         R_LoadQWSkin(&r_qwskincache[i], cl.scores[i].qw_skin);
7786                 t->currentskinframe = r_qwskincache[i].skinframe;
7787                 if (t->currentskinframe == NULL)
7788                         t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7789         }
7790         else if (t->numskinframes >= 2)
7791                 t->currentskinframe = t->skinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->skinframerate, t->numskinframes)];
7792         if (t->backgroundnumskinframes >= 2)
7793                 t->backgroundcurrentskinframe = t->backgroundskinframes[LoopingFrameNumberFromDouble(rsurface.shadertime * t->backgroundskinframerate, t->backgroundnumskinframes)];
7794
7795         t->currentmaterialflags = t->basematerialflags;
7796         t->currentalpha = rsurface.colormod[3];
7797         if (t->basematerialflags & MATERIALFLAG_WATERALPHA && (model->brush.supportwateralpha || r_novis.integer || r_trippy.integer))
7798                 t->currentalpha *= r_wateralpha.value;
7799         if(t->basematerialflags & MATERIALFLAG_WATERSHADER && r_fb.water.enabled && !r_refdef.view.isoverlay)
7800                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW; // we apply wateralpha later
7801         if(!r_fb.water.enabled || r_refdef.view.isoverlay)
7802                 t->currentmaterialflags &= ~(MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA);
7803         if (!(rsurface.ent_flags & RENDER_LIGHT))
7804                 t->currentmaterialflags |= MATERIALFLAG_FULLBRIGHT;
7805         else if (FAKELIGHT_ENABLED)
7806         {
7807                 // no modellight if using fakelight for the map
7808         }
7809         else if (rsurface.modeltexcoordlightmap2f == NULL && !(t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT))
7810         {
7811                 // pick a model lighting mode
7812                 if (VectorLength2(rsurface.modellight_diffuse) >= (1.0f / 256.0f))
7813                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL;
7814                 else
7815                         t->currentmaterialflags |= MATERIALFLAG_MODELLIGHT;
7816         }
7817         if (rsurface.ent_flags & RENDER_ADDITIVE)
7818                 t->currentmaterialflags |= MATERIALFLAG_ADD | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7819         else if (t->currentalpha < 1)
7820                 t->currentmaterialflags |= MATERIALFLAG_ALPHA | MATERIALFLAG_BLENDED | MATERIALFLAG_NOSHADOW;
7821         // LordHavoc: prevent bugs where code checks add or alpha at higher priority than customblend by clearing these flags
7822         if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7823                 t->currentmaterialflags &= ~(MATERIALFLAG_ADD | MATERIALFLAG_ALPHA);
7824         if (rsurface.ent_flags & RENDER_DOUBLESIDED)
7825                 t->currentmaterialflags |= MATERIALFLAG_NOSHADOW | MATERIALFLAG_NOCULLFACE;
7826         if (rsurface.ent_flags & (RENDER_NODEPTHTEST | RENDER_VIEWMODEL))
7827                 t->currentmaterialflags |= MATERIALFLAG_SHORTDEPTHRANGE;
7828         if (t->backgroundnumskinframes)
7829                 t->currentmaterialflags |= MATERIALFLAG_VERTEXTEXTUREBLEND;
7830         if (t->currentmaterialflags & MATERIALFLAG_BLENDED)
7831         {
7832                 if (t->currentmaterialflags & (MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA))
7833                         t->currentmaterialflags &= ~MATERIALFLAG_BLENDED;
7834         }
7835         else
7836                 t->currentmaterialflags &= ~(MATERIALFLAG_REFRACTION | MATERIALFLAG_WATERSHADER | MATERIALFLAG_CAMERA);
7837         if (vid.allowalphatocoverage && r_transparent_alphatocoverage.integer >= 2 && ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA | MATERIALFLAG_ADD | MATERIALFLAG_CUSTOMBLEND)) == (MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)))
7838         {
7839                 // promote alphablend to alphatocoverage (a type of alphatest) if antialiasing is on
7840                 t->currentmaterialflags = (t->currentmaterialflags & ~(MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHA)) | MATERIALFLAG_ALPHATEST;
7841         }
7842         if ((t->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST)) == MATERIALFLAG_BLENDED && r_transparentdepthmasking.integer && !(t->basematerialflags & MATERIALFLAG_BLENDED))
7843                 t->currentmaterialflags |= MATERIALFLAG_TRANSDEPTH;
7844
7845         // there is no tcmod
7846         if (t->currentmaterialflags & MATERIALFLAG_WATERSCROLL)
7847         {
7848                 t->currenttexmatrix = r_waterscrollmatrix;
7849                 t->currentbackgroundtexmatrix = r_waterscrollmatrix;
7850         }
7851         else if (!(t->currentmaterialflags & MATERIALFLAG_CUSTOMSURFACE))
7852         {
7853                 Matrix4x4_CreateIdentity(&t->currenttexmatrix);
7854                 Matrix4x4_CreateIdentity(&t->currentbackgroundtexmatrix);
7855         }
7856
7857         for (i = 0, tcmod = t->tcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7858                 R_tcMod_ApplyToMatrix(&t->currenttexmatrix, tcmod, t->currentmaterialflags);
7859         for (i = 0, tcmod = t->backgroundtcmods;i < Q3MAXTCMODS && tcmod->tcmod;i++, tcmod++)
7860                 R_tcMod_ApplyToMatrix(&t->currentbackgroundtexmatrix, tcmod, t->currentmaterialflags);
7861
7862         t->colormapping = VectorLength2(rsurface.colormap_pantscolor) + VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f);
7863         if (t->currentskinframe->qpixels)
7864                 R_SkinFrame_GenerateTexturesFromQPixels(t->currentskinframe, t->colormapping);
7865         t->basetexture = (!t->colormapping && t->currentskinframe->merged) ? t->currentskinframe->merged : t->currentskinframe->base;
7866         if (!t->basetexture)
7867                 t->basetexture = r_texture_notexture;
7868         t->pantstexture = t->colormapping ? t->currentskinframe->pants : NULL;
7869         t->shirttexture = t->colormapping ? t->currentskinframe->shirt : NULL;
7870         t->nmaptexture = t->currentskinframe->nmap;
7871         if (!t->nmaptexture)
7872                 t->nmaptexture = r_texture_blanknormalmap;
7873         t->glosstexture = r_texture_black;
7874         t->glowtexture = t->currentskinframe->glow;
7875         t->fogtexture = t->currentskinframe->fog;
7876         t->reflectmasktexture = t->currentskinframe->reflect;
7877         if (t->backgroundnumskinframes)
7878         {
7879                 t->backgroundbasetexture = (!t->colormapping && t->backgroundcurrentskinframe->merged) ? t->backgroundcurrentskinframe->merged : t->backgroundcurrentskinframe->base;
7880                 t->backgroundnmaptexture = t->backgroundcurrentskinframe->nmap;
7881                 t->backgroundglosstexture = r_texture_black;
7882                 t->backgroundglowtexture = t->backgroundcurrentskinframe->glow;
7883                 if (!t->backgroundnmaptexture)
7884                         t->backgroundnmaptexture = r_texture_blanknormalmap;
7885         }
7886         else
7887         {
7888                 t->backgroundbasetexture = r_texture_white;
7889                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7890                 t->backgroundglosstexture = r_texture_black;
7891                 t->backgroundglowtexture = NULL;
7892         }
7893         t->specularpower = r_shadow_glossexponent.value;
7894         // TODO: store reference values for these in the texture?
7895         t->specularscale = 0;
7896         if (r_shadow_gloss.integer > 0)
7897         {
7898                 if (t->currentskinframe->gloss || (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss))
7899                 {
7900                         if (r_shadow_glossintensity.value > 0)
7901                         {
7902                                 t->glosstexture = t->currentskinframe->gloss ? t->currentskinframe->gloss : r_texture_white;
7903                                 t->backgroundglosstexture = (t->backgroundcurrentskinframe && t->backgroundcurrentskinframe->gloss) ? t->backgroundcurrentskinframe->gloss : r_texture_white;
7904                                 t->specularscale = r_shadow_glossintensity.value;
7905                         }
7906                 }
7907                 else if (r_shadow_gloss.integer >= 2 && r_shadow_gloss2intensity.value > 0)
7908                 {
7909                         t->glosstexture = r_texture_white;
7910                         t->backgroundglosstexture = r_texture_white;
7911                         t->specularscale = r_shadow_gloss2intensity.value;
7912                         t->specularpower = r_shadow_gloss2exponent.value;
7913                 }
7914         }
7915         t->specularscale *= t->specularscalemod;
7916         t->specularpower *= t->specularpowermod;
7917         t->rtlightambient = 0;
7918
7919         // lightmaps mode looks bad with dlights using actual texturing, so turn
7920         // off the colormap and glossmap, but leave the normalmap on as it still
7921         // accurately represents the shading involved
7922         if (gl_lightmaps.integer)
7923         {
7924                 t->basetexture = r_texture_grey128;
7925                 t->pantstexture = r_texture_black;
7926                 t->shirttexture = r_texture_black;
7927                 t->nmaptexture = r_texture_blanknormalmap;
7928                 t->glosstexture = r_texture_black;
7929                 t->glowtexture = NULL;
7930                 t->fogtexture = NULL;
7931                 t->reflectmasktexture = NULL;
7932                 t->backgroundbasetexture = NULL;
7933                 t->backgroundnmaptexture = r_texture_blanknormalmap;
7934                 t->backgroundglosstexture = r_texture_black;
7935                 t->backgroundglowtexture = NULL;
7936                 t->specularscale = 0;
7937                 t->currentmaterialflags = MATERIALFLAG_WALL | (t->currentmaterialflags & (MATERIALFLAG_NOCULLFACE | MATERIALFLAG_MODELLIGHT | MATERIALFLAG_MODELLIGHT_DIRECTIONAL | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SHORTDEPTHRANGE));
7938         }
7939
7940         Vector4Set(t->lightmapcolor, rsurface.colormod[0], rsurface.colormod[1], rsurface.colormod[2], t->currentalpha);
7941         VectorClear(t->dlightcolor);
7942         t->currentnumlayers = 0;
7943         if (t->currentmaterialflags & MATERIALFLAG_WALL)
7944         {
7945                 int blendfunc1, blendfunc2;
7946                 qboolean depthmask;
7947                 if (t->currentmaterialflags & MATERIALFLAG_ADD)
7948                 {
7949                         blendfunc1 = GL_SRC_ALPHA;
7950                         blendfunc2 = GL_ONE;
7951                 }
7952                 else if (t->currentmaterialflags & MATERIALFLAG_ALPHA)
7953                 {
7954                         blendfunc1 = GL_SRC_ALPHA;
7955                         blendfunc2 = GL_ONE_MINUS_SRC_ALPHA;
7956                 }
7957                 else if (t->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
7958                 {
7959                         blendfunc1 = t->customblendfunc[0];
7960                         blendfunc2 = t->customblendfunc[1];
7961                 }
7962                 else
7963                 {
7964                         blendfunc1 = GL_ONE;
7965                         blendfunc2 = GL_ZERO;
7966                 }
7967                 // don't colormod evilblend textures
7968                 if(!R_BlendFuncFlags(blendfunc1, blendfunc2) & BLENDFUNC_ALLOWS_COLORMOD)
7969                         VectorSet(t->lightmapcolor, 1, 1, 1);
7970                 depthmask = !(t->currentmaterialflags & MATERIALFLAG_BLENDED);
7971                 if (t->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
7972                 {
7973                         // fullbright is not affected by r_refdef.lightmapintensity
7974                         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]);
7975                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
7976                                 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]);
7977                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
7978                                 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]);
7979                 }
7980                 else
7981                 {
7982                         vec3_t ambientcolor;
7983                         float colorscale;
7984                         // set the color tint used for lights affecting this surface
7985                         VectorSet(t->dlightcolor, t->lightmapcolor[0] * t->lightmapcolor[3], t->lightmapcolor[1] * t->lightmapcolor[3], t->lightmapcolor[2] * t->lightmapcolor[3]);
7986                         colorscale = 2;
7987                         // q3bsp has no lightmap updates, so the lightstylevalue that
7988                         // would normally be baked into the lightmap must be
7989                         // applied to the color
7990                         // FIXME: r_glsl 1 rendering doesn't support overbright lightstyles with this (the default light style is not overbright)
7991                         if (model->type == mod_brushq3)
7992                                 colorscale *= r_refdef.scene.rtlightstylevalue[0];
7993                         colorscale *= r_refdef.lightmapintensity;
7994                         VectorScale(t->lightmapcolor, r_refdef.scene.ambient, ambientcolor);
7995                         VectorScale(t->lightmapcolor, colorscale, t->lightmapcolor);
7996                         // basic lit geometry
7997                         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]);
7998                         // add pants/shirt if needed
7999                         if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8000                                 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]);
8001                         if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8002                                 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]);
8003                         // now add ambient passes if needed
8004                         if (VectorLength2(ambientcolor) >= (1.0f/1048576.0f))
8005                         {
8006                                 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]);
8007                                 if (VectorLength2(rsurface.colormap_pantscolor) >= (1.0f / 1048576.0f) && t->pantstexture)
8008                                         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]);
8009                                 if (VectorLength2(rsurface.colormap_shirtcolor) >= (1.0f / 1048576.0f) && t->shirttexture)
8010                                         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]);
8011                         }
8012                 }
8013                 if (t->glowtexture != NULL && !gl_lightmaps.integer)
8014                         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]);
8015                 if (r_refdef.fogenabled && !(t->currentmaterialflags & MATERIALFLAG_ADD))
8016                 {
8017                         // if this is opaque use alpha blend which will darken the earlier
8018                         // passes cheaply.
8019                         //
8020                         // if this is an alpha blended material, all the earlier passes
8021                         // were darkened by fog already, so we only need to add the fog
8022                         // color ontop through the fog mask texture
8023                         //
8024                         // if this is an additive blended material, all the earlier passes
8025                         // were darkened by fog already, and we should not add fog color
8026                         // (because the background was not darkened, there is no fog color
8027                         // that was lost behind it).
8028                         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]);
8029                 }
8030         }
8031
8032         return t->currentframe;
8033 }
8034
8035 rsurfacestate_t rsurface;
8036
8037 void RSurf_ActiveWorldEntity(void)
8038 {
8039         dp_model_t *model = r_refdef.scene.worldmodel;
8040         //if (rsurface.entity == r_refdef.scene.worldentity)
8041         //      return;
8042         rsurface.entity = r_refdef.scene.worldentity;
8043         rsurface.skeleton = NULL;
8044         memset(rsurface.userwavefunc_param, 0, sizeof(rsurface.userwavefunc_param));
8045         rsurface.ent_skinnum = 0;
8046         rsurface.ent_qwskin = -1;
8047         rsurface.ent_flags = r_refdef.scene.worldentity->flags;
8048         rsurface.shadertime = r_refdef.scene.time;
8049         rsurface.matrix = identitymatrix;
8050         rsurface.inversematrix = identitymatrix;
8051         rsurface.matrixscale = 1;
8052         rsurface.inversematrixscale = 1;
8053         R_EntityMatrix(&identitymatrix);
8054         VectorCopy(r_refdef.view.origin, rsurface.localvieworigin);
8055         Vector4Copy(r_refdef.fogplane, rsurface.fogplane);
8056         rsurface.fograngerecip = r_refdef.fograngerecip;
8057         rsurface.fogheightfade = r_refdef.fogheightfade;
8058         rsurface.fogplaneviewdist = r_refdef.fogplaneviewdist;
8059         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8060         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8061         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8062         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8063         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8064         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8065         VectorSet(rsurface.colormod, r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale);
8066         rsurface.colormod[3] = 1;
8067         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);
8068         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8069         rsurface.frameblend[0].lerp = 1;
8070         rsurface.ent_alttextures = false;
8071         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8072         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8073         rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8074         rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8075         rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8076         rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8077         rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8078         rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8079         rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8080         rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8081         rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8082         rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8083         rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8084         rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8085         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8086         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8087         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8088         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8089         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8090         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8091         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8092         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8093         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8094         rsurface.modelelement3i = model->surfmesh.data_element3i;
8095         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8096         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8097         rsurface.modelelement3s = model->surfmesh.data_element3s;
8098         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8099         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8100         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8101         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8102         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8103         rsurface.modelsurfaces = model->data_surfaces;
8104         rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8105         rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8106         rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8107         rsurface.modelgeneratedvertex = false;
8108         rsurface.batchgeneratedvertex = false;
8109         rsurface.batchfirstvertex = 0;
8110         rsurface.batchnumvertices = 0;
8111         rsurface.batchfirsttriangle = 0;
8112         rsurface.batchnumtriangles = 0;
8113         rsurface.batchvertex3f  = NULL;
8114         rsurface.batchvertex3f_vertexbuffer = NULL;
8115         rsurface.batchvertex3f_bufferoffset = 0;
8116         rsurface.batchsvector3f = NULL;
8117         rsurface.batchsvector3f_vertexbuffer = NULL;
8118         rsurface.batchsvector3f_bufferoffset = 0;
8119         rsurface.batchtvector3f = NULL;
8120         rsurface.batchtvector3f_vertexbuffer = NULL;
8121         rsurface.batchtvector3f_bufferoffset = 0;
8122         rsurface.batchnormal3f  = NULL;
8123         rsurface.batchnormal3f_vertexbuffer = NULL;
8124         rsurface.batchnormal3f_bufferoffset = 0;
8125         rsurface.batchlightmapcolor4f = NULL;
8126         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8127         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8128         rsurface.batchtexcoordtexture2f = NULL;
8129         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8130         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8131         rsurface.batchtexcoordlightmap2f = NULL;
8132         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8133         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8134         rsurface.batchvertexmesh = NULL;
8135         rsurface.batchvertexmeshbuffer = NULL;
8136         rsurface.batchvertex3fbuffer = NULL;
8137         rsurface.batchelement3i = NULL;
8138         rsurface.batchelement3i_indexbuffer = NULL;
8139         rsurface.batchelement3i_bufferoffset = 0;
8140         rsurface.batchelement3s = NULL;
8141         rsurface.batchelement3s_indexbuffer = NULL;
8142         rsurface.batchelement3s_bufferoffset = 0;
8143         rsurface.passcolor4f = NULL;
8144         rsurface.passcolor4f_vertexbuffer = NULL;
8145         rsurface.passcolor4f_bufferoffset = 0;
8146 }
8147
8148 void RSurf_ActiveModelEntity(const entity_render_t *ent, qboolean wantnormals, qboolean wanttangents, qboolean prepass)
8149 {
8150         dp_model_t *model = ent->model;
8151         //if (rsurface.entity == ent && (!model->surfmesh.isanimated || (!wantnormals && !wanttangents)))
8152         //      return;
8153         rsurface.entity = (entity_render_t *)ent;
8154         rsurface.skeleton = ent->skeleton;
8155         memcpy(rsurface.userwavefunc_param, ent->userwavefunc_param, sizeof(rsurface.userwavefunc_param));
8156         rsurface.ent_skinnum = ent->skinnum;
8157         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;
8158         rsurface.ent_flags = ent->flags;
8159         rsurface.shadertime = r_refdef.scene.time - ent->shadertime;
8160         rsurface.matrix = ent->matrix;
8161         rsurface.inversematrix = ent->inversematrix;
8162         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8163         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8164         R_EntityMatrix(&rsurface.matrix);
8165         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8166         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8167         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8168         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8169         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8170         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8171         VectorCopy(ent->modellight_ambient, rsurface.modellight_ambient);
8172         VectorCopy(ent->modellight_diffuse, rsurface.modellight_diffuse);
8173         VectorCopy(ent->modellight_lightdir, rsurface.modellight_lightdir);
8174         VectorCopy(ent->colormap_pantscolor, rsurface.colormap_pantscolor);
8175         VectorCopy(ent->colormap_shirtcolor, rsurface.colormap_shirtcolor);
8176         VectorScale(ent->colormod, r_refdef.view.colorscale, rsurface.colormod);
8177         rsurface.colormod[3] = ent->alpha;
8178         VectorScale(ent->glowmod, r_refdef.view.colorscale * r_hdr_glowintensity.value, rsurface.glowmod);
8179         memcpy(rsurface.frameblend, ent->frameblend, sizeof(ent->frameblend));
8180         rsurface.ent_alttextures = ent->framegroupblend[0].frame != 0;
8181         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8182         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8183         if (ent->model->brush.submodel && !prepass)
8184         {
8185                 rsurface.basepolygonfactor += r_polygonoffset_submodel_factor.value;
8186                 rsurface.basepolygonoffset += r_polygonoffset_submodel_offset.value;
8187         }
8188         if (model->surfmesh.isanimated && model->AnimateVertices)
8189         {
8190                 if (ent->animcache_vertex3f)
8191                 {
8192                         rsurface.modelvertex3f = ent->animcache_vertex3f;
8193                         rsurface.modelsvector3f = wanttangents ? ent->animcache_svector3f : NULL;
8194                         rsurface.modeltvector3f = wanttangents ? ent->animcache_tvector3f : NULL;
8195                         rsurface.modelnormal3f = wantnormals ? ent->animcache_normal3f : NULL;
8196                         rsurface.modelvertexmesh = ent->animcache_vertexmesh;
8197                         rsurface.modelvertexmeshbuffer = ent->animcache_vertexmeshbuffer;
8198                         rsurface.modelvertex3fbuffer = ent->animcache_vertex3fbuffer;
8199                 }
8200                 else if (wanttangents)
8201                 {
8202                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8203                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8204                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8205                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8206                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, rsurface.modelsvector3f, rsurface.modeltvector3f);
8207                         rsurface.modelvertexmesh = NULL;
8208                         rsurface.modelvertexmeshbuffer = NULL;
8209                         rsurface.modelvertex3fbuffer = NULL;
8210                 }
8211                 else if (wantnormals)
8212                 {
8213                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8214                         rsurface.modelsvector3f = NULL;
8215                         rsurface.modeltvector3f = NULL;
8216                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8217                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, rsurface.modelnormal3f, NULL, NULL);
8218                         rsurface.modelvertexmesh = NULL;
8219                         rsurface.modelvertexmeshbuffer = NULL;
8220                         rsurface.modelvertex3fbuffer = NULL;
8221                 }
8222                 else
8223                 {
8224                         rsurface.modelvertex3f = (float *)R_FrameData_Alloc(model->surfmesh.num_vertices * sizeof(float[3]));
8225                         rsurface.modelsvector3f = NULL;
8226                         rsurface.modeltvector3f = NULL;
8227                         rsurface.modelnormal3f = NULL;
8228                         model->AnimateVertices(model, rsurface.frameblend, rsurface.skeleton, rsurface.modelvertex3f, NULL, NULL, NULL);
8229                         rsurface.modelvertexmesh = NULL;
8230                         rsurface.modelvertexmeshbuffer = NULL;
8231                         rsurface.modelvertex3fbuffer = NULL;
8232                 }
8233                 rsurface.modelvertex3f_vertexbuffer = 0;
8234                 rsurface.modelvertex3f_bufferoffset = 0;
8235                 rsurface.modelsvector3f_vertexbuffer = 0;
8236                 rsurface.modelsvector3f_bufferoffset = 0;
8237                 rsurface.modeltvector3f_vertexbuffer = 0;
8238                 rsurface.modeltvector3f_bufferoffset = 0;
8239                 rsurface.modelnormal3f_vertexbuffer = 0;
8240                 rsurface.modelnormal3f_bufferoffset = 0;
8241                 rsurface.modelgeneratedvertex = true;
8242         }
8243         else
8244         {
8245                 rsurface.modelvertex3f  = model->surfmesh.data_vertex3f;
8246                 rsurface.modelvertex3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8247                 rsurface.modelvertex3f_bufferoffset = model->surfmesh.vbooffset_vertex3f;
8248                 rsurface.modelsvector3f = model->surfmesh.data_svector3f;
8249                 rsurface.modelsvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8250                 rsurface.modelsvector3f_bufferoffset = model->surfmesh.vbooffset_svector3f;
8251                 rsurface.modeltvector3f = model->surfmesh.data_tvector3f;
8252                 rsurface.modeltvector3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8253                 rsurface.modeltvector3f_bufferoffset = model->surfmesh.vbooffset_tvector3f;
8254                 rsurface.modelnormal3f  = model->surfmesh.data_normal3f;
8255                 rsurface.modelnormal3f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8256                 rsurface.modelnormal3f_bufferoffset = model->surfmesh.vbooffset_normal3f;
8257                 rsurface.modelvertexmesh = model->surfmesh.vertexmesh;
8258                 rsurface.modelvertexmeshbuffer = model->surfmesh.vertexmeshbuffer;
8259                 rsurface.modelvertex3fbuffer = model->surfmesh.vertex3fbuffer;
8260                 rsurface.modelgeneratedvertex = false;
8261         }
8262         rsurface.modellightmapcolor4f  = model->surfmesh.data_lightmapcolor4f;
8263         rsurface.modellightmapcolor4f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8264         rsurface.modellightmapcolor4f_bufferoffset = model->surfmesh.vbooffset_lightmapcolor4f;
8265         rsurface.modeltexcoordtexture2f  = model->surfmesh.data_texcoordtexture2f;
8266         rsurface.modeltexcoordtexture2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8267         rsurface.modeltexcoordtexture2f_bufferoffset = model->surfmesh.vbooffset_texcoordtexture2f;
8268         rsurface.modeltexcoordlightmap2f  = model->surfmesh.data_texcoordlightmap2f;
8269         rsurface.modeltexcoordlightmap2f_vertexbuffer = model->surfmesh.vbo_vertexbuffer;
8270         rsurface.modeltexcoordlightmap2f_bufferoffset = model->surfmesh.vbooffset_texcoordlightmap2f;
8271         rsurface.modelelement3i = model->surfmesh.data_element3i;
8272         rsurface.modelelement3i_indexbuffer = model->surfmesh.data_element3i_indexbuffer;
8273         rsurface.modelelement3i_bufferoffset = model->surfmesh.data_element3i_bufferoffset;
8274         rsurface.modelelement3s = model->surfmesh.data_element3s;
8275         rsurface.modelelement3s_indexbuffer = model->surfmesh.data_element3s_indexbuffer;
8276         rsurface.modelelement3s_bufferoffset = model->surfmesh.data_element3s_bufferoffset;
8277         rsurface.modellightmapoffsets = model->surfmesh.data_lightmapoffsets;
8278         rsurface.modelnumvertices = model->surfmesh.num_vertices;
8279         rsurface.modelnumtriangles = model->surfmesh.num_triangles;
8280         rsurface.modelsurfaces = model->data_surfaces;
8281         rsurface.batchgeneratedvertex = false;
8282         rsurface.batchfirstvertex = 0;
8283         rsurface.batchnumvertices = 0;
8284         rsurface.batchfirsttriangle = 0;
8285         rsurface.batchnumtriangles = 0;
8286         rsurface.batchvertex3f  = NULL;
8287         rsurface.batchvertex3f_vertexbuffer = NULL;
8288         rsurface.batchvertex3f_bufferoffset = 0;
8289         rsurface.batchsvector3f = NULL;
8290         rsurface.batchsvector3f_vertexbuffer = NULL;
8291         rsurface.batchsvector3f_bufferoffset = 0;
8292         rsurface.batchtvector3f = NULL;
8293         rsurface.batchtvector3f_vertexbuffer = NULL;
8294         rsurface.batchtvector3f_bufferoffset = 0;
8295         rsurface.batchnormal3f  = NULL;
8296         rsurface.batchnormal3f_vertexbuffer = NULL;
8297         rsurface.batchnormal3f_bufferoffset = 0;
8298         rsurface.batchlightmapcolor4f = NULL;
8299         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8300         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8301         rsurface.batchtexcoordtexture2f = NULL;
8302         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8303         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8304         rsurface.batchtexcoordlightmap2f = NULL;
8305         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8306         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8307         rsurface.batchvertexmesh = NULL;
8308         rsurface.batchvertexmeshbuffer = NULL;
8309         rsurface.batchvertex3fbuffer = NULL;
8310         rsurface.batchelement3i = NULL;
8311         rsurface.batchelement3i_indexbuffer = NULL;
8312         rsurface.batchelement3i_bufferoffset = 0;
8313         rsurface.batchelement3s = NULL;
8314         rsurface.batchelement3s_indexbuffer = NULL;
8315         rsurface.batchelement3s_bufferoffset = 0;
8316         rsurface.passcolor4f = NULL;
8317         rsurface.passcolor4f_vertexbuffer = NULL;
8318         rsurface.passcolor4f_bufferoffset = 0;
8319 }
8320
8321 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)
8322 {
8323         rsurface.entity = r_refdef.scene.worldentity;
8324         rsurface.skeleton = NULL;
8325         rsurface.ent_skinnum = 0;
8326         rsurface.ent_qwskin = -1;
8327         rsurface.ent_flags = entflags;
8328         rsurface.shadertime = r_refdef.scene.time - shadertime;
8329         rsurface.modelnumvertices = numvertices;
8330         rsurface.modelnumtriangles = numtriangles;
8331         rsurface.matrix = *matrix;
8332         rsurface.inversematrix = *inversematrix;
8333         rsurface.matrixscale = Matrix4x4_ScaleFromMatrix(&rsurface.matrix);
8334         rsurface.inversematrixscale = 1.0f / rsurface.matrixscale;
8335         R_EntityMatrix(&rsurface.matrix);
8336         Matrix4x4_Transform(&rsurface.inversematrix, r_refdef.view.origin, rsurface.localvieworigin);
8337         Matrix4x4_TransformStandardPlane(&rsurface.inversematrix, r_refdef.fogplane[0], r_refdef.fogplane[1], r_refdef.fogplane[2], r_refdef.fogplane[3], rsurface.fogplane);
8338         rsurface.fogplaneviewdist *= rsurface.inversematrixscale;
8339         rsurface.fograngerecip = r_refdef.fograngerecip * rsurface.matrixscale;
8340         rsurface.fogheightfade = r_refdef.fogheightfade * rsurface.matrixscale;
8341         rsurface.fogmasktabledistmultiplier = FOGMASKTABLEWIDTH * rsurface.fograngerecip;
8342         VectorSet(rsurface.modellight_ambient, 0, 0, 0);
8343         VectorSet(rsurface.modellight_diffuse, 0, 0, 0);
8344         VectorSet(rsurface.modellight_lightdir, 0, 0, 1);
8345         VectorSet(rsurface.colormap_pantscolor, 0, 0, 0);
8346         VectorSet(rsurface.colormap_shirtcolor, 0, 0, 0);
8347         Vector4Set(rsurface.colormod, r * r_refdef.view.colorscale, g * r_refdef.view.colorscale, b * r_refdef.view.colorscale, a);
8348         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);
8349         memset(rsurface.frameblend, 0, sizeof(rsurface.frameblend));
8350         rsurface.frameblend[0].lerp = 1;
8351         rsurface.ent_alttextures = false;
8352         rsurface.basepolygonfactor = r_refdef.polygonfactor;
8353         rsurface.basepolygonoffset = r_refdef.polygonoffset;
8354         if (wanttangents)
8355         {
8356                 rsurface.modelvertex3f = (float *)vertex3f;
8357                 rsurface.modelsvector3f = svector3f ? (float *)svector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8358                 rsurface.modeltvector3f = tvector3f ? (float *)tvector3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8359                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8360         }
8361         else if (wantnormals)
8362         {
8363                 rsurface.modelvertex3f = (float *)vertex3f;
8364                 rsurface.modelsvector3f = NULL;
8365                 rsurface.modeltvector3f = NULL;
8366                 rsurface.modelnormal3f = normal3f ? (float *)normal3f : (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8367         }
8368         else
8369         {
8370                 rsurface.modelvertex3f = (float *)vertex3f;
8371                 rsurface.modelsvector3f = NULL;
8372                 rsurface.modeltvector3f = NULL;
8373                 rsurface.modelnormal3f = NULL;
8374         }
8375         rsurface.modelvertexmesh = NULL;
8376         rsurface.modelvertexmeshbuffer = NULL;
8377         rsurface.modelvertex3fbuffer = NULL;
8378         rsurface.modelvertex3f_vertexbuffer = 0;
8379         rsurface.modelvertex3f_bufferoffset = 0;
8380         rsurface.modelsvector3f_vertexbuffer = 0;
8381         rsurface.modelsvector3f_bufferoffset = 0;
8382         rsurface.modeltvector3f_vertexbuffer = 0;
8383         rsurface.modeltvector3f_bufferoffset = 0;
8384         rsurface.modelnormal3f_vertexbuffer = 0;
8385         rsurface.modelnormal3f_bufferoffset = 0;
8386         rsurface.modelgeneratedvertex = true;
8387         rsurface.modellightmapcolor4f  = (float *)color4f;
8388         rsurface.modellightmapcolor4f_vertexbuffer = 0;
8389         rsurface.modellightmapcolor4f_bufferoffset = 0;
8390         rsurface.modeltexcoordtexture2f  = (float *)texcoord2f;
8391         rsurface.modeltexcoordtexture2f_vertexbuffer = 0;
8392         rsurface.modeltexcoordtexture2f_bufferoffset = 0;
8393         rsurface.modeltexcoordlightmap2f  = NULL;
8394         rsurface.modeltexcoordlightmap2f_vertexbuffer = 0;
8395         rsurface.modeltexcoordlightmap2f_bufferoffset = 0;
8396         rsurface.modelelement3i = (int *)element3i;
8397         rsurface.modelelement3i_indexbuffer = NULL;
8398         rsurface.modelelement3i_bufferoffset = 0;
8399         rsurface.modelelement3s = (unsigned short *)element3s;
8400         rsurface.modelelement3s_indexbuffer = NULL;
8401         rsurface.modelelement3s_bufferoffset = 0;
8402         rsurface.modellightmapoffsets = NULL;
8403         rsurface.modelsurfaces = NULL;
8404         rsurface.batchgeneratedvertex = false;
8405         rsurface.batchfirstvertex = 0;
8406         rsurface.batchnumvertices = 0;
8407         rsurface.batchfirsttriangle = 0;
8408         rsurface.batchnumtriangles = 0;
8409         rsurface.batchvertex3f  = NULL;
8410         rsurface.batchvertex3f_vertexbuffer = NULL;
8411         rsurface.batchvertex3f_bufferoffset = 0;
8412         rsurface.batchsvector3f = NULL;
8413         rsurface.batchsvector3f_vertexbuffer = NULL;
8414         rsurface.batchsvector3f_bufferoffset = 0;
8415         rsurface.batchtvector3f = NULL;
8416         rsurface.batchtvector3f_vertexbuffer = NULL;
8417         rsurface.batchtvector3f_bufferoffset = 0;
8418         rsurface.batchnormal3f  = NULL;
8419         rsurface.batchnormal3f_vertexbuffer = NULL;
8420         rsurface.batchnormal3f_bufferoffset = 0;
8421         rsurface.batchlightmapcolor4f = NULL;
8422         rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8423         rsurface.batchlightmapcolor4f_bufferoffset = 0;
8424         rsurface.batchtexcoordtexture2f = NULL;
8425         rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8426         rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8427         rsurface.batchtexcoordlightmap2f = NULL;
8428         rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8429         rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8430         rsurface.batchvertexmesh = NULL;
8431         rsurface.batchvertexmeshbuffer = NULL;
8432         rsurface.batchvertex3fbuffer = NULL;
8433         rsurface.batchelement3i = NULL;
8434         rsurface.batchelement3i_indexbuffer = NULL;
8435         rsurface.batchelement3i_bufferoffset = 0;
8436         rsurface.batchelement3s = NULL;
8437         rsurface.batchelement3s_indexbuffer = NULL;
8438         rsurface.batchelement3s_bufferoffset = 0;
8439         rsurface.passcolor4f = NULL;
8440         rsurface.passcolor4f_vertexbuffer = NULL;
8441         rsurface.passcolor4f_bufferoffset = 0;
8442
8443         if (rsurface.modelnumvertices && rsurface.modelelement3i)
8444         {
8445                 if ((wantnormals || wanttangents) && !normal3f)
8446                 {
8447                         rsurface.modelnormal3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8448                         Mod_BuildNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modelelement3i, rsurface.modelnormal3f, r_smoothnormals_areaweighting.integer != 0);
8449                 }
8450                 if (wanttangents && !svector3f)
8451                 {
8452                         rsurface.modelsvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8453                         rsurface.modeltvector3f = (float *)R_FrameData_Alloc(rsurface.modelnumvertices * sizeof(float[3]));
8454                         Mod_BuildTextureVectorsFromNormals(0, rsurface.modelnumvertices, rsurface.modelnumtriangles, rsurface.modelvertex3f, rsurface.modeltexcoordtexture2f, rsurface.modelnormal3f, rsurface.modelelement3i, rsurface.modelsvector3f, rsurface.modeltvector3f, r_smoothnormals_areaweighting.integer != 0);
8455                 }
8456         }
8457 }
8458
8459 float RSurf_FogPoint(const float *v)
8460 {
8461         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8462         float FogPlaneViewDist = r_refdef.fogplaneviewdist;
8463         float FogPlaneVertexDist = DotProduct(r_refdef.fogplane, v) + r_refdef.fogplane[3];
8464         float FogHeightFade = r_refdef.fogheightfade;
8465         float fogfrac;
8466         unsigned int fogmasktableindex;
8467         if (r_refdef.fogplaneviewabove)
8468                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8469         else
8470                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8471         fogmasktableindex = (unsigned int)(VectorDistance(r_refdef.view.origin, v) * fogfrac * r_refdef.fogmasktabledistmultiplier);
8472         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8473 }
8474
8475 float RSurf_FogVertex(const float *v)
8476 {
8477         // this code is identical to the USEFOGINSIDE/USEFOGOUTSIDE code in the shader
8478         float FogPlaneViewDist = rsurface.fogplaneviewdist;
8479         float FogPlaneVertexDist = DotProduct(rsurface.fogplane, v) + rsurface.fogplane[3];
8480         float FogHeightFade = rsurface.fogheightfade;
8481         float fogfrac;
8482         unsigned int fogmasktableindex;
8483         if (r_refdef.fogplaneviewabove)
8484                 fogfrac = min(0.0f, FogPlaneVertexDist) / (FogPlaneVertexDist - FogPlaneViewDist) * min(1.0f, min(0.0f, FogPlaneVertexDist) * FogHeightFade);
8485         else
8486                 fogfrac = FogPlaneViewDist / (FogPlaneViewDist - max(0.0f, FogPlaneVertexDist)) * min(1.0f, (min(0.0f, FogPlaneVertexDist) + FogPlaneViewDist) * FogHeightFade);
8487         fogmasktableindex = (unsigned int)(VectorDistance(rsurface.localvieworigin, v) * fogfrac * rsurface.fogmasktabledistmultiplier);
8488         return r_refdef.fogmasktable[min(fogmasktableindex, FOGMASKTABLEWIDTH - 1)];
8489 }
8490
8491 static void RSurf_RenumberElements(const int *inelement3i, int *outelement3i, int numelements, int adjust)
8492 {
8493         int i;
8494         for (i = 0;i < numelements;i++)
8495                 outelement3i[i] = inelement3i[i] + adjust;
8496 }
8497
8498 static const int quadedges[6][2] = {{0, 1}, {0, 2}, {0, 3}, {1, 2}, {1, 3}, {2, 3}};
8499 extern cvar_t gl_vbo;
8500 void RSurf_PrepareVerticesForBatch(int batchneed, int texturenumsurfaces, const msurface_t **texturesurfacelist)
8501 {
8502         int deformindex;
8503         int firsttriangle;
8504         int numtriangles;
8505         int firstvertex;
8506         int endvertex;
8507         int numvertices;
8508         int surfacefirsttriangle;
8509         int surfacenumtriangles;
8510         int surfacefirstvertex;
8511         int surfaceendvertex;
8512         int surfacenumvertices;
8513         int batchnumvertices;
8514         int batchnumtriangles;
8515         int needsupdate;
8516         int i, j;
8517         qboolean gaps;
8518         qboolean dynamicvertex;
8519         float amplitude;
8520         float animpos;
8521         float scale;
8522         float center[3], forward[3], right[3], up[3], v[3], newforward[3], newright[3], newup[3];
8523         float waveparms[4];
8524         q3shaderinfo_deform_t *deform;
8525         const msurface_t *surface, *firstsurface;
8526         r_vertexmesh_t *vertexmesh;
8527         if (!texturenumsurfaces)
8528                 return;
8529         // find vertex range of this surface batch
8530         gaps = false;
8531         firstsurface = texturesurfacelist[0];
8532         firsttriangle = firstsurface->num_firsttriangle;
8533         batchnumvertices = 0;
8534         batchnumtriangles = 0;
8535         firstvertex = endvertex = firstsurface->num_firstvertex;
8536         for (i = 0;i < texturenumsurfaces;i++)
8537         {
8538                 surface = texturesurfacelist[i];
8539                 if (surface != firstsurface + i)
8540                         gaps = true;
8541                 surfacefirstvertex = surface->num_firstvertex;
8542                 surfaceendvertex = surfacefirstvertex + surface->num_vertices;
8543                 surfacenumvertices = surface->num_vertices;
8544                 surfacenumtriangles = surface->num_triangles;
8545                 if (firstvertex > surfacefirstvertex)
8546                         firstvertex = surfacefirstvertex;
8547                 if (endvertex < surfaceendvertex)
8548                         endvertex = surfaceendvertex;
8549                 batchnumvertices += surfacenumvertices;
8550                 batchnumtriangles += surfacenumtriangles;
8551         }
8552
8553         // we now know the vertex range used, and if there are any gaps in it
8554         rsurface.batchfirstvertex = firstvertex;
8555         rsurface.batchnumvertices = endvertex - firstvertex;
8556         rsurface.batchfirsttriangle = firsttriangle;
8557         rsurface.batchnumtriangles = batchnumtriangles;
8558
8559         // this variable holds flags for which properties have been updated that
8560         // may require regenerating vertexmesh array...
8561         needsupdate = 0;
8562
8563         // check if any dynamic vertex processing must occur
8564         dynamicvertex = false;
8565
8566         // if there is a chance of animated vertex colors, it's a dynamic batch
8567         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8568         {
8569                 dynamicvertex = true;
8570                 batchneed |= BATCHNEED_NOGAPS;
8571                 needsupdate |= BATCHNEED_VERTEXMESH_VERTEXCOLOR;
8572         }
8573
8574         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8575         {
8576                 switch (deform->deform)
8577                 {
8578                 default:
8579                 case Q3DEFORM_PROJECTIONSHADOW:
8580                 case Q3DEFORM_TEXT0:
8581                 case Q3DEFORM_TEXT1:
8582                 case Q3DEFORM_TEXT2:
8583                 case Q3DEFORM_TEXT3:
8584                 case Q3DEFORM_TEXT4:
8585                 case Q3DEFORM_TEXT5:
8586                 case Q3DEFORM_TEXT6:
8587                 case Q3DEFORM_TEXT7:
8588                 case Q3DEFORM_NONE:
8589                         break;
8590                 case Q3DEFORM_AUTOSPRITE:
8591                         dynamicvertex = true;
8592                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8593                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8594                         break;
8595                 case Q3DEFORM_AUTOSPRITE2:
8596                         dynamicvertex = true;
8597                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8598                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8599                         break;
8600                 case Q3DEFORM_NORMAL:
8601                         dynamicvertex = true;
8602                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8603                         needsupdate |= BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8604                         break;
8605                 case Q3DEFORM_WAVE:
8606                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8607                                 break; // if wavefunc is a nop, ignore this transform
8608                         dynamicvertex = true;
8609                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8610                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8611                         break;
8612                 case Q3DEFORM_BULGE:
8613                         dynamicvertex = true;
8614                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8615                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR;
8616                         break;
8617                 case Q3DEFORM_MOVE:
8618                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
8619                                 break; // if wavefunc is a nop, ignore this transform
8620                         dynamicvertex = true;
8621                         batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8622                         needsupdate |= BATCHNEED_VERTEXMESH_VERTEX;
8623                         break;
8624                 }
8625         }
8626         switch(rsurface.texture->tcgen.tcgen)
8627         {
8628         default:
8629         case Q3TCGEN_TEXTURE:
8630                 break;
8631         case Q3TCGEN_LIGHTMAP:
8632                 dynamicvertex = true;
8633                 batchneed |= BATCHNEED_ARRAY_LIGHTMAP | BATCHNEED_NOGAPS;
8634                 needsupdate |= BATCHNEED_VERTEXMESH_LIGHTMAP;
8635                 break;
8636         case Q3TCGEN_VECTOR:
8637                 dynamicvertex = true;
8638                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS;
8639                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8640                 break;
8641         case Q3TCGEN_ENVIRONMENT:
8642                 dynamicvertex = true;
8643                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS;
8644                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8645                 break;
8646         }
8647         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
8648         {
8649                 dynamicvertex = true;
8650                 batchneed |= BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_NOGAPS;
8651                 needsupdate |= BATCHNEED_VERTEXMESH_TEXCOORD;
8652         }
8653
8654         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8655         {
8656                 dynamicvertex = true;
8657                 batchneed |= BATCHNEED_NOGAPS;
8658                 needsupdate |= (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP));
8659         }
8660
8661         if (dynamicvertex || gaps || rsurface.batchfirstvertex)
8662         {
8663                 // when copying, we need to consider the regeneration of vertexmesh, any dependencies it may have must be set...
8664                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)      batchneed |= BATCHNEED_ARRAY_VERTEX;
8665                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)      batchneed |= BATCHNEED_ARRAY_NORMAL;
8666                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)      batchneed |= BATCHNEED_ARRAY_VECTOR;
8667                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) batchneed |= BATCHNEED_ARRAY_VERTEXCOLOR;
8668                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)    batchneed |= BATCHNEED_ARRAY_TEXCOORD;
8669                 if (batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP)    batchneed |= BATCHNEED_ARRAY_LIGHTMAP;
8670         }
8671
8672         // when the model data has no vertex buffer (dynamic mesh), we need to
8673         // eliminate gaps
8674         if (vid.useinterleavedarrays ? !rsurface.modelvertexmeshbuffer : !rsurface.modelvertex3f_vertexbuffer)
8675                 batchneed |= BATCHNEED_NOGAPS;
8676
8677         // if needsupdate, we have to do a dynamic vertex batch for sure
8678         if (needsupdate & batchneed)
8679                 dynamicvertex = true;
8680
8681         // see if we need to build vertexmesh from arrays
8682         if (!rsurface.modelvertexmesh && (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)))
8683                 dynamicvertex = true;
8684
8685         // if gaps are unacceptable, and there are gaps, it's a dynamic batch...
8686         // also some drivers strongly dislike firstvertex
8687         if ((batchneed & BATCHNEED_NOGAPS) && (gaps || firstvertex))
8688                 dynamicvertex = true;
8689
8690         rsurface.batchvertex3f = rsurface.modelvertex3f;
8691         rsurface.batchvertex3f_vertexbuffer = rsurface.modelvertex3f_vertexbuffer;
8692         rsurface.batchvertex3f_bufferoffset = rsurface.modelvertex3f_bufferoffset;
8693         rsurface.batchsvector3f = rsurface.modelsvector3f;
8694         rsurface.batchsvector3f_vertexbuffer = rsurface.modelsvector3f_vertexbuffer;
8695         rsurface.batchsvector3f_bufferoffset = rsurface.modelsvector3f_bufferoffset;
8696         rsurface.batchtvector3f = rsurface.modeltvector3f;
8697         rsurface.batchtvector3f_vertexbuffer = rsurface.modeltvector3f_vertexbuffer;
8698         rsurface.batchtvector3f_bufferoffset = rsurface.modeltvector3f_bufferoffset;
8699         rsurface.batchnormal3f = rsurface.modelnormal3f;
8700         rsurface.batchnormal3f_vertexbuffer = rsurface.modelnormal3f_vertexbuffer;
8701         rsurface.batchnormal3f_bufferoffset = rsurface.modelnormal3f_bufferoffset;
8702         rsurface.batchlightmapcolor4f = rsurface.modellightmapcolor4f;
8703         rsurface.batchlightmapcolor4f_vertexbuffer  = rsurface.modellightmapcolor4f_vertexbuffer;
8704         rsurface.batchlightmapcolor4f_bufferoffset  = rsurface.modellightmapcolor4f_bufferoffset;
8705         rsurface.batchtexcoordtexture2f = rsurface.modeltexcoordtexture2f;
8706         rsurface.batchtexcoordtexture2f_vertexbuffer  = rsurface.modeltexcoordtexture2f_vertexbuffer;
8707         rsurface.batchtexcoordtexture2f_bufferoffset  = rsurface.modeltexcoordtexture2f_bufferoffset;
8708         rsurface.batchtexcoordlightmap2f = rsurface.modeltexcoordlightmap2f;
8709         rsurface.batchtexcoordlightmap2f_vertexbuffer = rsurface.modeltexcoordlightmap2f_vertexbuffer;
8710         rsurface.batchtexcoordlightmap2f_bufferoffset = rsurface.modeltexcoordlightmap2f_bufferoffset;
8711         rsurface.batchvertex3fbuffer = rsurface.modelvertex3fbuffer;
8712         rsurface.batchvertexmesh = rsurface.modelvertexmesh;
8713         rsurface.batchvertexmeshbuffer = rsurface.modelvertexmeshbuffer;
8714         rsurface.batchelement3i = rsurface.modelelement3i;
8715         rsurface.batchelement3i_indexbuffer = rsurface.modelelement3i_indexbuffer;
8716         rsurface.batchelement3i_bufferoffset = rsurface.modelelement3i_bufferoffset;
8717         rsurface.batchelement3s = rsurface.modelelement3s;
8718         rsurface.batchelement3s_indexbuffer = rsurface.modelelement3s_indexbuffer;
8719         rsurface.batchelement3s_bufferoffset = rsurface.modelelement3s_bufferoffset;
8720
8721         // if any dynamic vertex processing has to occur in software, we copy the
8722         // entire surface list together before processing to rebase the vertices
8723         // to start at 0 (otherwise we waste a lot of room in a vertex buffer).
8724         //
8725         // if any gaps exist and we do not have a static vertex buffer, we have to
8726         // copy the surface list together to avoid wasting upload bandwidth on the
8727         // vertices in the gaps.
8728         //
8729         // if gaps exist and we have a static vertex buffer, we still have to
8730         // combine the index buffer ranges into one dynamic index buffer.
8731         //
8732         // in all cases we end up with data that can be drawn in one call.
8733
8734         if (!dynamicvertex)
8735         {
8736                 // static vertex data, just set pointers...
8737                 rsurface.batchgeneratedvertex = false;
8738                 // if there are gaps, we want to build a combined index buffer,
8739                 // otherwise use the original static buffer with an appropriate offset
8740                 if (gaps)
8741                 {
8742                         // build a new triangle elements array for this batch
8743                         rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8744                         rsurface.batchfirsttriangle = 0;
8745                         numtriangles = 0;
8746                         for (i = 0;i < texturenumsurfaces;i++)
8747                         {
8748                                 surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8749                                 surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8750                                 memcpy(rsurface.batchelement3i + 3*numtriangles, rsurface.modelelement3i + 3*surfacefirsttriangle, surfacenumtriangles*sizeof(int[3]));
8751                                 numtriangles += surfacenumtriangles;
8752                         }
8753                         rsurface.batchelement3i_indexbuffer = NULL;
8754                         rsurface.batchelement3i_bufferoffset = 0;
8755                         rsurface.batchelement3s = NULL;
8756                         rsurface.batchelement3s_indexbuffer = NULL;
8757                         rsurface.batchelement3s_bufferoffset = 0;
8758                         if (endvertex <= 65536)
8759                         {
8760                                 // make a 16bit (unsigned short) index array if possible
8761                                 rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8762                                 for (i = 0;i < numtriangles*3;i++)
8763                                         rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8764                         }
8765                 }
8766                 return;
8767         }
8768
8769         // something needs software processing, do it for real...
8770         // we only directly handle separate array data in this case and then
8771         // generate interleaved data if needed...
8772         rsurface.batchgeneratedvertex = true;
8773
8774         // now copy the vertex data into a combined array and make an index array
8775         // (this is what Quake3 does all the time)
8776         //if (gaps || rsurface.batchfirstvertex)
8777         {
8778                 rsurface.batchvertex3fbuffer = NULL;
8779                 rsurface.batchvertexmesh = NULL;
8780                 rsurface.batchvertexmeshbuffer = NULL;
8781                 rsurface.batchvertex3f = NULL;
8782                 rsurface.batchvertex3f_vertexbuffer = NULL;
8783                 rsurface.batchvertex3f_bufferoffset = 0;
8784                 rsurface.batchsvector3f = NULL;
8785                 rsurface.batchsvector3f_vertexbuffer = NULL;
8786                 rsurface.batchsvector3f_bufferoffset = 0;
8787                 rsurface.batchtvector3f = NULL;
8788                 rsurface.batchtvector3f_vertexbuffer = NULL;
8789                 rsurface.batchtvector3f_bufferoffset = 0;
8790                 rsurface.batchnormal3f = NULL;
8791                 rsurface.batchnormal3f_vertexbuffer = NULL;
8792                 rsurface.batchnormal3f_bufferoffset = 0;
8793                 rsurface.batchlightmapcolor4f = NULL;
8794                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8795                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8796                 rsurface.batchtexcoordtexture2f = NULL;
8797                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
8798                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
8799                 rsurface.batchtexcoordlightmap2f = NULL;
8800                 rsurface.batchtexcoordlightmap2f_vertexbuffer = NULL;
8801                 rsurface.batchtexcoordlightmap2f_bufferoffset = 0;
8802                 rsurface.batchelement3i = (int *)R_FrameData_Alloc(batchnumtriangles * sizeof(int[3]));
8803                 rsurface.batchelement3i_indexbuffer = NULL;
8804                 rsurface.batchelement3i_bufferoffset = 0;
8805                 rsurface.batchelement3s = NULL;
8806                 rsurface.batchelement3s_indexbuffer = NULL;
8807                 rsurface.batchelement3s_bufferoffset = 0;
8808                 // we'll only be setting up certain arrays as needed
8809                 if (batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
8810                         rsurface.batchvertexmesh = (r_vertexmesh_t *)R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
8811                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8812                         rsurface.batchvertex3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8813                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8814                         rsurface.batchnormal3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8815                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8816                 {
8817                         rsurface.batchsvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8818                         rsurface.batchtvector3f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
8819                 }
8820                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8821                         rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8822                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8823                         rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8824                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8825                         rsurface.batchtexcoordlightmap2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
8826                 numvertices = 0;
8827                 numtriangles = 0;
8828                 for (i = 0;i < texturenumsurfaces;i++)
8829                 {
8830                         surfacefirstvertex = texturesurfacelist[i]->num_firstvertex;
8831                         surfacenumvertices = texturesurfacelist[i]->num_vertices;
8832                         surfacefirsttriangle = texturesurfacelist[i]->num_firsttriangle;
8833                         surfacenumtriangles = texturesurfacelist[i]->num_triangles;
8834                         // copy only the data requested
8835                         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP)) && rsurface.modelvertexmesh)
8836                                 memcpy(rsurface.batchvertexmesh + numvertices, rsurface.modelvertexmesh + surfacefirstvertex, surfacenumvertices * sizeof(rsurface.batchvertexmesh[0]));
8837                         if (batchneed & (BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_ARRAY_TEXCOORD | BATCHNEED_ARRAY_LIGHTMAP))
8838                         {
8839                                 if (batchneed & BATCHNEED_ARRAY_VERTEX)
8840                                 {
8841                                         if (rsurface.batchvertex3f)
8842                                                 memcpy(rsurface.batchvertex3f + 3*numvertices, rsurface.modelvertex3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8843                                         else
8844                                                 memset(rsurface.batchvertex3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8845                                 }
8846                                 if (batchneed & BATCHNEED_ARRAY_NORMAL)
8847                                 {
8848                                         if (rsurface.modelnormal3f)
8849                                                 memcpy(rsurface.batchnormal3f + 3*numvertices, rsurface.modelnormal3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8850                                         else
8851                                                 memset(rsurface.batchnormal3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8852                                 }
8853                                 if (batchneed & BATCHNEED_ARRAY_VECTOR)
8854                                 {
8855                                         if (rsurface.modelsvector3f)
8856                                         {
8857                                                 memcpy(rsurface.batchsvector3f + 3*numvertices, rsurface.modelsvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8858                                                 memcpy(rsurface.batchtvector3f + 3*numvertices, rsurface.modeltvector3f + 3*surfacefirstvertex, surfacenumvertices * sizeof(float[3]));
8859                                         }
8860                                         else
8861                                         {
8862                                                 memset(rsurface.batchsvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8863                                                 memset(rsurface.batchtvector3f + 3*numvertices, 0, surfacenumvertices * sizeof(float[3]));
8864                                         }
8865                                 }
8866                                 if (batchneed & BATCHNEED_ARRAY_VERTEXCOLOR)
8867                                 {
8868                                         if (rsurface.modellightmapcolor4f)
8869                                                 memcpy(rsurface.batchlightmapcolor4f + 4*numvertices, rsurface.modellightmapcolor4f + 4*surfacefirstvertex, surfacenumvertices * sizeof(float[4]));
8870                                         else
8871                                                 memset(rsurface.batchlightmapcolor4f + 4*numvertices, 0, surfacenumvertices * sizeof(float[4]));
8872                                 }
8873                                 if (batchneed & BATCHNEED_ARRAY_TEXCOORD)
8874                                 {
8875                                         if (rsurface.modeltexcoordtexture2f)
8876                                                 memcpy(rsurface.batchtexcoordtexture2f + 2*numvertices, rsurface.modeltexcoordtexture2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8877                                         else
8878                                                 memset(rsurface.batchtexcoordtexture2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8879                                 }
8880                                 if (batchneed & BATCHNEED_ARRAY_LIGHTMAP)
8881                                 {
8882                                         if (rsurface.modeltexcoordlightmap2f)
8883                                                 memcpy(rsurface.batchtexcoordlightmap2f + 2*numvertices, rsurface.modeltexcoordlightmap2f + 2*surfacefirstvertex, surfacenumvertices * sizeof(float[2]));
8884                                         else
8885                                                 memset(rsurface.batchtexcoordlightmap2f + 2*numvertices, 0, surfacenumvertices * sizeof(float[2]));
8886                                 }
8887                         }
8888                         RSurf_RenumberElements(rsurface.modelelement3i + 3*surfacefirsttriangle, rsurface.batchelement3i + 3*numtriangles, 3*surfacenumtriangles, numvertices - surfacefirstvertex);
8889                         numvertices += surfacenumvertices;
8890                         numtriangles += surfacenumtriangles;
8891                 }
8892
8893                 // generate a 16bit index array as well if possible
8894                 // (in general, dynamic batches fit)
8895                 if (numvertices <= 65536)
8896                 {
8897                         rsurface.batchelement3s = (unsigned short *)R_FrameData_Alloc(batchnumtriangles * sizeof(unsigned short[3]));
8898                         for (i = 0;i < numtriangles*3;i++)
8899                                 rsurface.batchelement3s[i] = rsurface.batchelement3i[i];
8900                 }
8901
8902                 // since we've copied everything, the batch now starts at 0
8903                 rsurface.batchfirstvertex = 0;
8904                 rsurface.batchnumvertices = batchnumvertices;
8905                 rsurface.batchfirsttriangle = 0;
8906                 rsurface.batchnumtriangles = batchnumtriangles;
8907         }
8908
8909         // q1bsp surfaces rendered in vertex color mode have to have colors
8910         // calculated based on lightstyles
8911         if ((batchneed & (BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_ARRAY_VERTEXCOLOR)) && texturesurfacelist[0]->lightmapinfo)
8912         {
8913                 // generate color arrays for the surfaces in this list
8914                 int c[4];
8915                 int scale;
8916                 int size3;
8917                 const int *offsets;
8918                 const unsigned char *lm;
8919                 rsurface.batchlightmapcolor4f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[4]));
8920                 rsurface.batchlightmapcolor4f_vertexbuffer = NULL;
8921                 rsurface.batchlightmapcolor4f_bufferoffset = 0;
8922                 numvertices = 0;
8923                 for (i = 0;i < texturenumsurfaces;i++)
8924                 {
8925                         surface = texturesurfacelist[i];
8926                         offsets = rsurface.modellightmapoffsets + surface->num_firstvertex;
8927                         surfacenumvertices = surface->num_vertices;
8928                         if (surface->lightmapinfo->samples)
8929                         {
8930                                 for (j = 0;j < surfacenumvertices;j++)
8931                                 {
8932                                         lm = surface->lightmapinfo->samples + offsets[j];
8933                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[0]];
8934                                         VectorScale(lm, scale, c);
8935                                         if (surface->lightmapinfo->styles[1] != 255)
8936                                         {
8937                                                 size3 = ((surface->lightmapinfo->extents[0]>>4)+1)*((surface->lightmapinfo->extents[1]>>4)+1)*3;
8938                                                 lm += size3;
8939                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[1]];
8940                                                 VectorMA(c, scale, lm, c);
8941                                                 if (surface->lightmapinfo->styles[2] != 255)
8942                                                 {
8943                                                         lm += size3;
8944                                                         scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[2]];
8945                                                         VectorMA(c, scale, lm, c);
8946                                                         if (surface->lightmapinfo->styles[3] != 255)
8947                                                         {
8948                                                                 lm += size3;
8949                                                                 scale = r_refdef.scene.lightstylevalue[surface->lightmapinfo->styles[3]];
8950                                                                 VectorMA(c, scale, lm, c);
8951                                                         }
8952                                                 }
8953                                         }
8954                                         c[0] >>= 7;
8955                                         c[1] >>= 7;
8956                                         c[2] >>= 7;
8957                                         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);
8958                                         numvertices++;
8959                                 }
8960                         }
8961                         else
8962                         {
8963                                 for (j = 0;j < surfacenumvertices;j++)
8964                                 {
8965                                         Vector4Set(rsurface.batchlightmapcolor4f + 4*numvertices, 0, 0, 0, 1);
8966                                         numvertices++;
8967                                 }
8968                         }
8969                 }
8970         }
8971
8972         // if vertices are deformed (sprite flares and things in maps, possibly
8973         // water waves, bulges and other deformations), modify the copied vertices
8974         // in place
8975         for (deformindex = 0, deform = rsurface.texture->deforms;deformindex < Q3MAXDEFORMS && deform->deform && r_deformvertexes.integer;deformindex++, deform++)
8976         {
8977                 switch (deform->deform)
8978                 {
8979                 default:
8980                 case Q3DEFORM_PROJECTIONSHADOW:
8981                 case Q3DEFORM_TEXT0:
8982                 case Q3DEFORM_TEXT1:
8983                 case Q3DEFORM_TEXT2:
8984                 case Q3DEFORM_TEXT3:
8985                 case Q3DEFORM_TEXT4:
8986                 case Q3DEFORM_TEXT5:
8987                 case Q3DEFORM_TEXT6:
8988                 case Q3DEFORM_TEXT7:
8989                 case Q3DEFORM_NONE:
8990                         break;
8991                 case Q3DEFORM_AUTOSPRITE:
8992                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
8993                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
8994                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
8995                         VectorNormalize(newforward);
8996                         VectorNormalize(newright);
8997                         VectorNormalize(newup);
8998 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
8999 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9000 //                      rsurface.batchvertex3f_bufferoffset = 0;
9001 //                      rsurface.batchsvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchsvector3f);
9002 //                      rsurface.batchsvector3f_vertexbuffer = NULL;
9003 //                      rsurface.batchsvector3f_bufferoffset = 0;
9004 //                      rsurface.batchtvector3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchtvector3f);
9005 //                      rsurface.batchtvector3f_vertexbuffer = NULL;
9006 //                      rsurface.batchtvector3f_bufferoffset = 0;
9007 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9008 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9009 //                      rsurface.batchnormal3f_bufferoffset = 0;
9010                         // sometimes we're on a renderpath that does not use vectors (GL11/GL13/GLES1)
9011                         if (!VectorLength2(rsurface.batchnormal3f + 3*rsurface.batchfirstvertex))
9012                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9013                         if (!VectorLength2(rsurface.batchsvector3f + 3*rsurface.batchfirstvertex))
9014                                 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);
9015                         // a single autosprite surface can contain multiple sprites...
9016                         for (j = 0;j < batchnumvertices - 3;j += 4)
9017                         {
9018                                 VectorClear(center);
9019                                 for (i = 0;i < 4;i++)
9020                                         VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9021                                 VectorScale(center, 0.25f, center);
9022                                 VectorCopy(rsurface.batchnormal3f + 3*j, forward);
9023                                 VectorCopy(rsurface.batchsvector3f + 3*j, right);
9024                                 VectorCopy(rsurface.batchtvector3f + 3*j, up);
9025                                 for (i = 0;i < 4;i++)
9026                                 {
9027                                         VectorSubtract(rsurface.batchvertex3f + 3*(j+i), center, v);
9028                                         VectorMAMAMAM(1, center, DotProduct(forward, v), newforward, DotProduct(right, v), newright, DotProduct(up, v), newup, rsurface.batchvertex3f + 3*(j+i));
9029                                 }
9030                         }
9031                         // if we get here, BATCHNEED_ARRAY_NORMAL and BATCHNEED_ARRAY_VECTOR are in batchneed, so no need to check
9032                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9033                         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);
9034                         break;
9035                 case Q3DEFORM_AUTOSPRITE2:
9036                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, newforward);
9037                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.right, newright);
9038                         Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.up, newup);
9039                         VectorNormalize(newforward);
9040                         VectorNormalize(newright);
9041                         VectorNormalize(newup);
9042 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9043 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9044 //                      rsurface.batchvertex3f_bufferoffset = 0;
9045                         {
9046                                 const float *v1, *v2;
9047                                 vec3_t start, end;
9048                                 float f, l;
9049                                 struct
9050                                 {
9051                                         float length2;
9052                                         const float *v1;
9053                                         const float *v2;
9054                                 }
9055                                 shortest[2];
9056                                 memset(shortest, 0, sizeof(shortest));
9057                                 // a single autosprite surface can contain multiple sprites...
9058                                 for (j = 0;j < batchnumvertices - 3;j += 4)
9059                                 {
9060                                         VectorClear(center);
9061                                         for (i = 0;i < 4;i++)
9062                                                 VectorAdd(center, rsurface.batchvertex3f + 3*(j+i), center);
9063                                         VectorScale(center, 0.25f, center);
9064                                         // find the two shortest edges, then use them to define the
9065                                         // axis vectors for rotating around the central axis
9066                                         for (i = 0;i < 6;i++)
9067                                         {
9068                                                 v1 = rsurface.batchvertex3f + 3*(j+quadedges[i][0]);
9069                                                 v2 = rsurface.batchvertex3f + 3*(j+quadedges[i][1]);
9070                                                 l = VectorDistance2(v1, v2);
9071                                                 // this length bias tries to make sense of square polygons, assuming they are meant to be upright
9072                                                 if (v1[2] != v2[2])
9073                                                         l += (1.0f / 1024.0f);
9074                                                 if (shortest[0].length2 > l || i == 0)
9075                                                 {
9076                                                         shortest[1] = shortest[0];
9077                                                         shortest[0].length2 = l;
9078                                                         shortest[0].v1 = v1;
9079                                                         shortest[0].v2 = v2;
9080                                                 }
9081                                                 else if (shortest[1].length2 > l || i == 1)
9082                                                 {
9083                                                         shortest[1].length2 = l;
9084                                                         shortest[1].v1 = v1;
9085                                                         shortest[1].v2 = v2;
9086                                                 }
9087                                         }
9088                                         VectorLerp(shortest[0].v1, 0.5f, shortest[0].v2, start);
9089                                         VectorLerp(shortest[1].v1, 0.5f, shortest[1].v2, end);
9090                                         // this calculates the right vector from the shortest edge
9091                                         // and the up vector from the edge midpoints
9092                                         VectorSubtract(shortest[0].v1, shortest[0].v2, right);
9093                                         VectorNormalize(right);
9094                                         VectorSubtract(end, start, up);
9095                                         VectorNormalize(up);
9096                                         // calculate a forward vector to use instead of the original plane normal (this is how we get a new right vector)
9097                                         VectorSubtract(rsurface.localvieworigin, center, forward);
9098                                         //Matrix4x4_Transform3x3(&rsurface.inversematrix, r_refdef.view.forward, forward);
9099                                         VectorNegate(forward, forward);
9100                                         VectorReflect(forward, 0, up, forward);
9101                                         VectorNormalize(forward);
9102                                         CrossProduct(up, forward, newright);
9103                                         VectorNormalize(newright);
9104                                         // rotate the quad around the up axis vector, this is made
9105                                         // especially easy by the fact we know the quad is flat,
9106                                         // so we only have to subtract the center position and
9107                                         // measure distance along the right vector, and then
9108                                         // multiply that by the newright vector and add back the
9109                                         // center position
9110                                         // we also need to subtract the old position to undo the
9111                                         // displacement from the center, which we do with a
9112                                         // DotProduct, the subtraction/addition of center is also
9113                                         // optimized into DotProducts here
9114                                         l = DotProduct(right, center);
9115                                         for (i = 0;i < 4;i++)
9116                                         {
9117                                                 v1 = rsurface.batchvertex3f + 3*(j+i);
9118                                                 f = DotProduct(right, v1) - l;
9119                                                 VectorMAMAM(1, v1, -f, right, f, newright, rsurface.batchvertex3f + 3*(j+i));
9120                                         }
9121                                 }
9122                         }
9123                         if(batchneed & (BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR)) // otherwise these can stay NULL
9124                         {
9125 //                              rsurface.batchnormal3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9126 //                              rsurface.batchnormal3f_vertexbuffer = NULL;
9127 //                              rsurface.batchnormal3f_bufferoffset = 0;
9128                                 Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9129                         }
9130                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9131                         {
9132 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9133 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9134 //                              rsurface.batchsvector3f_bufferoffset = 0;
9135 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9136 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9137 //                              rsurface.batchtvector3f_bufferoffset = 0;
9138                                 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);
9139                         }
9140                         break;
9141                 case Q3DEFORM_NORMAL:
9142                         // deform the normals to make reflections wavey
9143                         rsurface.batchnormal3f = (float *)R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9144                         rsurface.batchnormal3f_vertexbuffer = NULL;
9145                         rsurface.batchnormal3f_bufferoffset = 0;
9146                         for (j = 0;j < batchnumvertices;j++)
9147                         {
9148                                 float vertex[3];
9149                                 float *normal = rsurface.batchnormal3f + 3*j;
9150                                 VectorScale(rsurface.batchvertex3f + 3*j, 0.98f, vertex);
9151                                 normal[0] = rsurface.batchnormal3f[j*3+0] + deform->parms[0] * noise4f(      vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9152                                 normal[1] = rsurface.batchnormal3f[j*3+1] + deform->parms[0] * noise4f( 98 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9153                                 normal[2] = rsurface.batchnormal3f[j*3+2] + deform->parms[0] * noise4f(196 + vertex[0], vertex[1], vertex[2], rsurface.shadertime * deform->parms[1]);
9154                                 VectorNormalize(normal);
9155                         }
9156                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9157                         {
9158 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9159 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9160 //                              rsurface.batchsvector3f_bufferoffset = 0;
9161 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9162 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9163 //                              rsurface.batchtvector3f_bufferoffset = 0;
9164                                 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);
9165                         }
9166                         break;
9167                 case Q3DEFORM_WAVE:
9168                         // deform vertex array to make wavey water and flags and such
9169                         waveparms[0] = deform->waveparms[0];
9170                         waveparms[1] = deform->waveparms[1];
9171                         waveparms[2] = deform->waveparms[2];
9172                         waveparms[3] = deform->waveparms[3];
9173                         if(!R_TestQ3WaveFunc(deform->wavefunc, waveparms))
9174                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9175                         // this is how a divisor of vertex influence on deformation
9176                         animpos = deform->parms[0] ? 1.0f / deform->parms[0] : 100.0f;
9177                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9178 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9179 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9180 //                      rsurface.batchvertex3f_bufferoffset = 0;
9181 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9182 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9183 //                      rsurface.batchnormal3f_bufferoffset = 0;
9184                         for (j = 0;j < batchnumvertices;j++)
9185                         {
9186                                 // if the wavefunc depends on time, evaluate it per-vertex
9187                                 if (waveparms[3])
9188                                 {
9189                                         waveparms[2] = deform->waveparms[2] + (rsurface.batchvertex3f[j*3+0] + rsurface.batchvertex3f[j*3+1] + rsurface.batchvertex3f[j*3+2]) * animpos;
9190                                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, waveparms);
9191                                 }
9192                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9193                         }
9194                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9195                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9196                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9197                         {
9198 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9199 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9200 //                              rsurface.batchsvector3f_bufferoffset = 0;
9201 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9202 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9203 //                              rsurface.batchtvector3f_bufferoffset = 0;
9204                                 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);
9205                         }
9206                         break;
9207                 case Q3DEFORM_BULGE:
9208                         // deform vertex array to make the surface have moving bulges
9209 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9210 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9211 //                      rsurface.batchvertex3f_bufferoffset = 0;
9212 //                      rsurface.batchnormal3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchnormal3f);
9213 //                      rsurface.batchnormal3f_vertexbuffer = NULL;
9214 //                      rsurface.batchnormal3f_bufferoffset = 0;
9215                         for (j = 0;j < batchnumvertices;j++)
9216                         {
9217                                 scale = sin(rsurface.batchtexcoordtexture2f[j*2+0] * deform->parms[0] + rsurface.shadertime * deform->parms[2]) * deform->parms[1];
9218                                 VectorMA(rsurface.batchvertex3f + 3*j, scale, rsurface.batchnormal3f + 3*j, rsurface.batchvertex3f + 3*j);
9219                         }
9220                         // if we get here, BATCHNEED_ARRAY_NORMAL is in batchneed, so no need to check
9221                         Mod_BuildNormals(rsurface.batchfirstvertex, batchnumvertices, batchnumtriangles, rsurface.batchvertex3f, rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle, rsurface.batchnormal3f, r_smoothnormals_areaweighting.integer != 0);
9222                         if(batchneed & BATCHNEED_ARRAY_VECTOR) // otherwise these can stay NULL
9223                         {
9224 //                              rsurface.batchsvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9225 //                              rsurface.batchsvector3f_vertexbuffer = NULL;
9226 //                              rsurface.batchsvector3f_bufferoffset = 0;
9227 //                              rsurface.batchtvector3f = R_FrameData_Alloc(batchnumvertices * sizeof(float[3]));
9228 //                              rsurface.batchtvector3f_vertexbuffer = NULL;
9229 //                              rsurface.batchtvector3f_bufferoffset = 0;
9230                                 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);
9231                         }
9232                         break;
9233                 case Q3DEFORM_MOVE:
9234                         // deform vertex array
9235                         if(!R_TestQ3WaveFunc(deform->wavefunc, deform->waveparms))
9236                                 break; // if wavefunc is a nop, don't make a dynamic vertex array
9237                         scale = R_EvaluateQ3WaveFunc(deform->wavefunc, deform->waveparms);
9238                         VectorScale(deform->parms, scale, waveparms);
9239 //                      rsurface.batchvertex3f = R_FrameData_Store(batchnumvertices * sizeof(float[3]), rsurface.batchvertex3f);
9240 //                      rsurface.batchvertex3f_vertexbuffer = NULL;
9241 //                      rsurface.batchvertex3f_bufferoffset = 0;
9242                         for (j = 0;j < batchnumvertices;j++)
9243                                 VectorAdd(rsurface.batchvertex3f + 3*j, waveparms, rsurface.batchvertex3f + 3*j);
9244                         break;
9245                 }
9246         }
9247
9248         // generate texcoords based on the chosen texcoord source
9249         switch(rsurface.texture->tcgen.tcgen)
9250         {
9251         default:
9252         case Q3TCGEN_TEXTURE:
9253                 break;
9254         case Q3TCGEN_LIGHTMAP:
9255 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9256 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9257 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9258                 if (rsurface.batchtexcoordlightmap2f)
9259                         memcpy(rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordtexture2f, batchnumvertices * sizeof(float[2]));
9260                 break;
9261         case Q3TCGEN_VECTOR:
9262 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9263 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9264 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9265                 for (j = 0;j < batchnumvertices;j++)
9266                 {
9267                         rsurface.batchtexcoordtexture2f[j*2+0] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms);
9268                         rsurface.batchtexcoordtexture2f[j*2+1] = DotProduct(rsurface.batchvertex3f + 3*j, rsurface.texture->tcgen.parms + 3);
9269                 }
9270                 break;
9271         case Q3TCGEN_ENVIRONMENT:
9272                 // make environment reflections using a spheremap
9273                 rsurface.batchtexcoordtexture2f = (float *)R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9274                 rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9275                 rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9276                 for (j = 0;j < batchnumvertices;j++)
9277                 {
9278                         // identical to Q3A's method, but executed in worldspace so
9279                         // carried models can be shiny too
9280
9281                         float viewer[3], d, reflected[3], worldreflected[3];
9282
9283                         VectorSubtract(rsurface.localvieworigin, rsurface.batchvertex3f + 3*j, viewer);
9284                         // VectorNormalize(viewer);
9285
9286                         d = DotProduct(rsurface.batchnormal3f + 3*j, viewer);
9287
9288                         reflected[0] = rsurface.batchnormal3f[j*3+0]*2*d - viewer[0];
9289                         reflected[1] = rsurface.batchnormal3f[j*3+1]*2*d - viewer[1];
9290                         reflected[2] = rsurface.batchnormal3f[j*3+2]*2*d - viewer[2];
9291                         // note: this is proportinal to viewer, so we can normalize later
9292
9293                         Matrix4x4_Transform3x3(&rsurface.matrix, reflected, worldreflected);
9294                         VectorNormalize(worldreflected);
9295
9296                         // note: this sphere map only uses world x and z!
9297                         // so positive and negative y will LOOK THE SAME.
9298                         rsurface.batchtexcoordtexture2f[j*2+0] = 0.5 + 0.5 * worldreflected[1];
9299                         rsurface.batchtexcoordtexture2f[j*2+1] = 0.5 - 0.5 * worldreflected[2];
9300                 }
9301                 break;
9302         }
9303         // the only tcmod that needs software vertex processing is turbulent, so
9304         // check for it here and apply the changes if needed
9305         // and we only support that as the first one
9306         // (handling a mixture of turbulent and other tcmods would be problematic
9307         //  without punting it entirely to a software path)
9308         if (rsurface.texture->tcmods[0].tcmod == Q3TCMOD_TURBULENT)
9309         {
9310                 amplitude = rsurface.texture->tcmods[0].parms[1];
9311                 animpos = rsurface.texture->tcmods[0].parms[2] + rsurface.shadertime * rsurface.texture->tcmods[0].parms[3];
9312 //              rsurface.batchtexcoordtexture2f = R_FrameData_Alloc(batchnumvertices * sizeof(float[2]));
9313 //              rsurface.batchtexcoordtexture2f_vertexbuffer = NULL;
9314 //              rsurface.batchtexcoordtexture2f_bufferoffset = 0;
9315                 for (j = 0;j < batchnumvertices;j++)
9316                 {
9317                         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);
9318                         rsurface.batchtexcoordtexture2f[j*2+1] += amplitude * sin(((rsurface.batchvertex3f[j*3+1]                                ) * 1.0 / 1024.0f + animpos) * M_PI * 2);
9319                 }
9320         }
9321
9322         if (needsupdate & batchneed & (BATCHNEED_VERTEXMESH_VERTEX | BATCHNEED_VERTEXMESH_NORMAL | BATCHNEED_VERTEXMESH_VECTOR | BATCHNEED_VERTEXMESH_VERTEXCOLOR | BATCHNEED_VERTEXMESH_TEXCOORD | BATCHNEED_VERTEXMESH_LIGHTMAP))
9323         {
9324                 // convert the modified arrays to vertex structs
9325 //              rsurface.batchvertexmesh = R_FrameData_Alloc(batchnumvertices * sizeof(r_vertexmesh_t));
9326 //              rsurface.batchvertexmeshbuffer = NULL;
9327                 if (batchneed & BATCHNEED_VERTEXMESH_VERTEX)
9328                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9329                                 VectorCopy(rsurface.batchvertex3f + 3*j, vertexmesh->vertex3f);
9330                 if (batchneed & BATCHNEED_VERTEXMESH_NORMAL)
9331                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9332                                 VectorCopy(rsurface.batchnormal3f + 3*j, vertexmesh->normal3f);
9333                 if (batchneed & BATCHNEED_VERTEXMESH_VECTOR)
9334                 {
9335                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9336                         {
9337                                 VectorCopy(rsurface.batchsvector3f + 3*j, vertexmesh->svector3f);
9338                                 VectorCopy(rsurface.batchtvector3f + 3*j, vertexmesh->tvector3f);
9339                         }
9340                 }
9341                 if ((batchneed & BATCHNEED_VERTEXMESH_VERTEXCOLOR) && rsurface.batchlightmapcolor4f)
9342                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9343                                 Vector4Copy(rsurface.batchlightmapcolor4f + 4*j, vertexmesh->color4f);
9344                 if (batchneed & BATCHNEED_VERTEXMESH_TEXCOORD)
9345                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9346                                 Vector2Copy(rsurface.batchtexcoordtexture2f + 2*j, vertexmesh->texcoordtexture2f);
9347                 if ((batchneed & BATCHNEED_VERTEXMESH_LIGHTMAP) && rsurface.batchtexcoordlightmap2f)
9348                         for (j = 0, vertexmesh = rsurface.batchvertexmesh;j < batchnumvertices;j++, vertexmesh++)
9349                                 Vector2Copy(rsurface.batchtexcoordlightmap2f + 2*j, vertexmesh->texcoordlightmap2f);
9350         }
9351 }
9352
9353 void RSurf_DrawBatch(void)
9354 {
9355         // sometimes a zero triangle surface (usually a degenerate patch) makes it
9356         // through the pipeline, killing it earlier in the pipeline would have
9357         // per-surface overhead rather than per-batch overhead, so it's best to
9358         // reject it here, before it hits glDraw.
9359         if (rsurface.batchnumtriangles == 0)
9360                 return;
9361 #if 0
9362         // batch debugging code
9363         if (r_test.integer && rsurface.entity == r_refdef.scene.worldentity && rsurface.batchvertex3f == r_refdef.scene.worldentity->model->surfmesh.data_vertex3f)
9364         {
9365                 int i;
9366                 int j;
9367                 int c;
9368                 const int *e;
9369                 e = rsurface.batchelement3i + rsurface.batchfirsttriangle*3;
9370                 for (i = 0;i < rsurface.batchnumtriangles*3;i++)
9371                 {
9372                         c = e[i];
9373                         for (j = 0;j < rsurface.entity->model->num_surfaces;j++)
9374                         {
9375                                 if (c >= rsurface.modelsurfaces[j].num_firstvertex && c < (rsurface.modelsurfaces[j].num_firstvertex + rsurface.modelsurfaces[j].num_vertices))
9376                                 {
9377                                         if (rsurface.modelsurfaces[j].texture != rsurface.texture)
9378                                                 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);
9379                                         break;
9380                                 }
9381                         }
9382                 }
9383         }
9384 #endif
9385         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);
9386 }
9387
9388 static int RSurf_FindWaterPlaneForSurface(const msurface_t *surface)
9389 {
9390         // pick the closest matching water plane
9391         int planeindex, vertexindex, bestplaneindex = -1;
9392         float d, bestd;
9393         vec3_t vert;
9394         const float *v;
9395         r_waterstate_waterplane_t *p;
9396         qboolean prepared = false;
9397         bestd = 0;
9398         for (planeindex = 0, p = r_fb.water.waterplanes;planeindex < r_fb.water.numwaterplanes;planeindex++, p++)
9399         {
9400                 if(p->camera_entity != rsurface.texture->camera_entity)
9401                         continue;
9402                 d = 0;
9403                 if(!prepared)
9404                 {
9405                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
9406                         prepared = true;
9407                         if(rsurface.batchnumvertices == 0)
9408                                 break;
9409                 }
9410                 for (vertexindex = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3;vertexindex < rsurface.batchnumvertices;vertexindex++, v += 3)
9411                 {
9412                         Matrix4x4_Transform(&rsurface.matrix, v, vert);
9413                         d += fabs(PlaneDiff(vert, &p->plane));
9414                 }
9415                 if (bestd > d || bestplaneindex < 0)
9416                 {
9417                         bestd = d;
9418                         bestplaneindex = planeindex;
9419                 }
9420         }
9421         return bestplaneindex;
9422         // NOTE: this MAY return a totally unrelated water plane; we can ignore
9423         // this situation though, as it might be better to render single larger
9424         // batches with useless stuff (backface culled for example) than to
9425         // render multiple smaller batches
9426 }
9427
9428 static void RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray(void)
9429 {
9430         int i;
9431         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9432         rsurface.passcolor4f_vertexbuffer = 0;
9433         rsurface.passcolor4f_bufferoffset = 0;
9434         for (i = 0;i < rsurface.batchnumvertices;i++)
9435                 Vector4Set(rsurface.passcolor4f + 4*i, 0.5f, 0.5f, 0.5f, 1.0f);
9436 }
9437
9438 static void RSurf_DrawBatch_GL11_ApplyFog(void)
9439 {
9440         int i;
9441         float f;
9442         const float *v;
9443         const float *c;
9444         float *c2;
9445         if (rsurface.passcolor4f)
9446         {
9447                 // generate color arrays
9448                 c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9449                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9450                 rsurface.passcolor4f_vertexbuffer = 0;
9451                 rsurface.passcolor4f_bufferoffset = 0;
9452                 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)
9453                 {
9454                         f = RSurf_FogVertex(v);
9455                         c2[0] = c[0] * f;
9456                         c2[1] = c[1] * f;
9457                         c2[2] = c[2] * f;
9458                         c2[3] = c[3];
9459                 }
9460         }
9461         else
9462         {
9463                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9464                 rsurface.passcolor4f_vertexbuffer = 0;
9465                 rsurface.passcolor4f_bufferoffset = 0;
9466                 for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c2 += 4)
9467                 {
9468                         f = RSurf_FogVertex(v);
9469                         c2[0] = f;
9470                         c2[1] = f;
9471                         c2[2] = f;
9472                         c2[3] = 1;
9473                 }
9474         }
9475 }
9476
9477 static void RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors(void)
9478 {
9479         int i;
9480         float f;
9481         const float *v;
9482         const float *c;
9483         float *c2;
9484         if (!rsurface.passcolor4f)
9485                 return;
9486         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9487         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9488         rsurface.passcolor4f_vertexbuffer = 0;
9489         rsurface.passcolor4f_bufferoffset = 0;
9490         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)
9491         {
9492                 f = RSurf_FogVertex(v);
9493                 c2[0] = c[0] * f + r_refdef.fogcolor[0] * (1 - f);
9494                 c2[1] = c[1] * f + r_refdef.fogcolor[1] * (1 - f);
9495                 c2[2] = c[2] * f + r_refdef.fogcolor[2] * (1 - f);
9496                 c2[3] = c[3];
9497         }
9498 }
9499
9500 static void RSurf_DrawBatch_GL11_ApplyColor(float r, float g, float b, float a)
9501 {
9502         int i;
9503         const float *c;
9504         float *c2;
9505         if (!rsurface.passcolor4f)
9506                 return;
9507         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9508         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9509         rsurface.passcolor4f_vertexbuffer = 0;
9510         rsurface.passcolor4f_bufferoffset = 0;
9511         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9512         {
9513                 c2[0] = c[0] * r;
9514                 c2[1] = c[1] * g;
9515                 c2[2] = c[2] * b;
9516                 c2[3] = c[3] * a;
9517         }
9518 }
9519
9520 static void RSurf_DrawBatch_GL11_ApplyAmbient(void)
9521 {
9522         int i;
9523         const float *c;
9524         float *c2;
9525         if (!rsurface.passcolor4f)
9526                 return;
9527         c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;
9528         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9529         rsurface.passcolor4f_vertexbuffer = 0;
9530         rsurface.passcolor4f_bufferoffset = 0;
9531         for (i = 0, c2 = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, c += 4, c2 += 4)
9532         {
9533                 c2[0] = c[0] + r_refdef.scene.ambient;
9534                 c2[1] = c[1] + r_refdef.scene.ambient;
9535                 c2[2] = c[2] + r_refdef.scene.ambient;
9536                 c2[3] = c[3];
9537         }
9538 }
9539
9540 static void RSurf_DrawBatch_GL11_Lightmap(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9541 {
9542         // TODO: optimize
9543         rsurface.passcolor4f = NULL;
9544         rsurface.passcolor4f_vertexbuffer = 0;
9545         rsurface.passcolor4f_bufferoffset = 0;
9546         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9547         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9548         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9549         GL_Color(r, g, b, a);
9550         R_Mesh_TexBind(0, rsurface.lightmaptexture);
9551         RSurf_DrawBatch();
9552 }
9553
9554 static void RSurf_DrawBatch_GL11_Unlit(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9555 {
9556         // TODO: optimize applyfog && applycolor case
9557         // just apply fog if necessary, and tint the fog color array if necessary
9558         rsurface.passcolor4f = NULL;
9559         rsurface.passcolor4f_vertexbuffer = 0;
9560         rsurface.passcolor4f_bufferoffset = 0;
9561         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9562         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9563         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9564         GL_Color(r, g, b, a);
9565         RSurf_DrawBatch();
9566 }
9567
9568 static void RSurf_DrawBatch_GL11_VertexColor(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9569 {
9570         // TODO: optimize
9571         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
9572         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
9573         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
9574         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9575         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9576         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9577         GL_Color(r, g, b, a);
9578         RSurf_DrawBatch();
9579 }
9580
9581 static void RSurf_DrawBatch_GL11_ClampColor(void)
9582 {
9583         int i;
9584         const float *c1;
9585         float *c2;
9586         if (!rsurface.passcolor4f)
9587                 return;
9588         for (i = 0, c1 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex, c2 = rsurface.passcolor4f + 4*rsurface.batchfirstvertex;i < rsurface.batchnumvertices;i++, c1 += 4, c2 += 4)
9589         {
9590                 c2[0] = bound(0.0f, c1[0], 1.0f);
9591                 c2[1] = bound(0.0f, c1[1], 1.0f);
9592                 c2[2] = bound(0.0f, c1[2], 1.0f);
9593                 c2[3] = bound(0.0f, c1[3], 1.0f);
9594         }
9595 }
9596
9597 static void RSurf_DrawBatch_GL11_ApplyFakeLight(void)
9598 {
9599         int i;
9600         float f;
9601         const float *v;
9602         const float *n;
9603         float *c;
9604         //vec3_t eyedir;
9605
9606         // fake shading
9607         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9608         rsurface.passcolor4f_vertexbuffer = 0;
9609         rsurface.passcolor4f_bufferoffset = 0;
9610         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)
9611         {
9612                 f = -DotProduct(r_refdef.view.forward, n);
9613                 f = max(0, f);
9614                 f = f * 0.85 + 0.15; // work around so stuff won't get black
9615                 f *= r_refdef.lightmapintensity;
9616                 Vector4Set(c, f, f, f, 1);
9617         }
9618 }
9619
9620 static void RSurf_DrawBatch_GL11_FakeLight(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9621 {
9622         RSurf_DrawBatch_GL11_ApplyFakeLight();
9623         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9624         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9625         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9626         GL_Color(r, g, b, a);
9627         RSurf_DrawBatch();
9628 }
9629
9630 static void RSurf_DrawBatch_GL11_ApplyVertexShade(float *r, float *g, float *b, float *a, qboolean *applycolor)
9631 {
9632         int i;
9633         float f;
9634         float alpha;
9635         const float *v;
9636         const float *n;
9637         float *c;
9638         vec3_t ambientcolor;
9639         vec3_t diffusecolor;
9640         vec3_t lightdir;
9641         // TODO: optimize
9642         // model lighting
9643         VectorCopy(rsurface.modellight_lightdir, lightdir);
9644         f = 0.5f * r_refdef.lightmapintensity;
9645         ambientcolor[0] = rsurface.modellight_ambient[0] * *r * f;
9646         ambientcolor[1] = rsurface.modellight_ambient[1] * *g * f;
9647         ambientcolor[2] = rsurface.modellight_ambient[2] * *b * f;
9648         diffusecolor[0] = rsurface.modellight_diffuse[0] * *r * f;
9649         diffusecolor[1] = rsurface.modellight_diffuse[1] * *g * f;
9650         diffusecolor[2] = rsurface.modellight_diffuse[2] * *b * f;
9651         alpha = *a;
9652         if (VectorLength2(diffusecolor) > 0)
9653         {
9654                 // q3-style directional shading
9655                 rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9656                 rsurface.passcolor4f_vertexbuffer = 0;
9657                 rsurface.passcolor4f_bufferoffset = 0;
9658                 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)
9659                 {
9660                         if ((f = DotProduct(n, lightdir)) > 0)
9661                                 VectorMA(ambientcolor, f, diffusecolor, c);
9662                         else
9663                                 VectorCopy(ambientcolor, c);
9664                         c[3] = alpha;
9665                 }
9666                 *r = 1;
9667                 *g = 1;
9668                 *b = 1;
9669                 *a = 1;
9670                 *applycolor = false;
9671         }
9672         else
9673         {
9674                 *r = ambientcolor[0];
9675                 *g = ambientcolor[1];
9676                 *b = ambientcolor[2];
9677                 rsurface.passcolor4f = NULL;
9678                 rsurface.passcolor4f_vertexbuffer = 0;
9679                 rsurface.passcolor4f_bufferoffset = 0;
9680         }
9681 }
9682
9683 static void RSurf_DrawBatch_GL11_VertexShade(float r, float g, float b, float a, qboolean applycolor, qboolean applyfog)
9684 {
9685         RSurf_DrawBatch_GL11_ApplyVertexShade(&r, &g, &b, &a, &applycolor);
9686         if (applyfog)   RSurf_DrawBatch_GL11_ApplyFog();
9687         if (applycolor) RSurf_DrawBatch_GL11_ApplyColor(r, g, b, a);
9688         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, rsurface.passcolor4f_vertexbuffer, rsurface.passcolor4f_bufferoffset);
9689         GL_Color(r, g, b, a);
9690         RSurf_DrawBatch();
9691 }
9692
9693 static void RSurf_DrawBatch_GL11_MakeFogColor(float r, float g, float b, float a)
9694 {
9695         int i;
9696         float f;
9697         const float *v;
9698         float *c;
9699
9700         // fake shading
9701         rsurface.passcolor4f = (float *)R_FrameData_Alloc(rsurface.batchnumvertices * sizeof(float[4]));
9702         rsurface.passcolor4f_vertexbuffer = 0;
9703         rsurface.passcolor4f_bufferoffset = 0;
9704
9705         for (i = 0, v = rsurface.batchvertex3f + rsurface.batchfirstvertex * 3, c = rsurface.passcolor4f + rsurface.batchfirstvertex * 4;i < rsurface.batchnumvertices;i++, v += 3, c += 4)
9706         {
9707                 f = 1 - RSurf_FogVertex(v);
9708                 c[0] = r;
9709                 c[1] = g;
9710                 c[2] = b;
9711                 c[3] = f * a;
9712         }
9713 }
9714
9715 void RSurf_SetupDepthAndCulling(void)
9716 {
9717         // submodels are biased to avoid z-fighting with world surfaces that they
9718         // may be exactly overlapping (avoids z-fighting artifacts on certain
9719         // doors and things in Quake maps)
9720         GL_DepthRange(0, (rsurface.texture->currentmaterialflags & MATERIALFLAG_SHORTDEPTHRANGE) ? 0.0625 : 1);
9721         GL_PolygonOffset(rsurface.basepolygonfactor + rsurface.texture->biaspolygonfactor, rsurface.basepolygonoffset + rsurface.texture->biaspolygonoffset);
9722         GL_DepthTest(!(rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST));
9723         GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
9724 }
9725
9726 static void R_DrawTextureSurfaceList_Sky(int texturenumsurfaces, const msurface_t **texturesurfacelist)
9727 {
9728         // transparent sky would be ridiculous
9729         if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
9730                 return;
9731         R_SetupShader_Generic_NoTexture(false, false);
9732         skyrenderlater = true;
9733         RSurf_SetupDepthAndCulling();
9734         GL_DepthMask(true);
9735         // LordHavoc: HalfLife maps have freaky skypolys so don't use
9736         // skymasking on them, and Quake3 never did sky masking (unlike
9737         // software Quake and software Quake2), so disable the sky masking
9738         // in Quake3 maps as it causes problems with q3map2 sky tricks,
9739         // and skymasking also looks very bad when noclipping outside the
9740         // level, so don't use it then either.
9741         if (r_refdef.scene.worldmodel && r_refdef.scene.worldmodel->type == mod_brushq1 && r_q1bsp_skymasking.integer && !r_refdef.viewcache.world_novis && !r_trippy.integer)
9742         {
9743                 R_Mesh_ResetTextureState();
9744                 if (skyrendermasked)
9745                 {
9746                         R_SetupShader_DepthOrShadow(false, false);
9747                         // depth-only (masking)
9748                         GL_ColorMask(0,0,0,0);
9749                         // just to make sure that braindead drivers don't draw
9750                         // anything despite that colormask...
9751                         GL_BlendFunc(GL_ZERO, GL_ONE);
9752                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9753                         if (rsurface.batchvertex3fbuffer)
9754                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
9755                         else
9756                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
9757                 }
9758                 else
9759                 {
9760                         R_SetupShader_Generic_NoTexture(false, false);
9761                         // fog sky
9762                         GL_BlendFunc(GL_ONE, GL_ZERO);
9763                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
9764                         GL_Color(r_refdef.fogcolor[0], r_refdef.fogcolor[1], r_refdef.fogcolor[2], 1);
9765                         R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
9766                 }
9767                 RSurf_DrawBatch();
9768                 if (skyrendermasked)
9769                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
9770         }
9771         R_Mesh_ResetTextureState();
9772         GL_Color(1, 1, 1, 1);
9773 }
9774
9775 extern rtexture_t *r_shadow_prepasslightingdiffusetexture;
9776 extern rtexture_t *r_shadow_prepasslightingspeculartexture;
9777 static void R_DrawTextureSurfaceList_GL20(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
9778 {
9779         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_REFLECTION | MATERIALFLAG_CAMERA)))
9780                 return;
9781         if (prepass)
9782         {
9783                 // render screenspace normalmap to texture
9784                 GL_DepthMask(true);
9785                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_DEFERREDGEOMETRY, texturenumsurfaces, texturesurfacelist, NULL, false);
9786                 RSurf_DrawBatch();
9787                 return;
9788         }
9789
9790         // bind lightmap texture
9791
9792         // water/refraction/reflection/camera surfaces have to be handled specially
9793         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA | MATERIALFLAG_REFLECTION)))
9794         {
9795                 int start, end, startplaneindex;
9796                 for (start = 0;start < texturenumsurfaces;start = end)
9797                 {
9798                         startplaneindex = RSurf_FindWaterPlaneForSurface(texturesurfacelist[start]);
9799                         if(startplaneindex < 0)
9800                         {
9801                                 // this happens if the plane e.g. got backface culled and thus didn't get a water plane. We can just ignore this.
9802                                 // Con_Printf("No matching water plane for surface with material flags 0x%08x - PLEASE DEBUG THIS\n", rsurface.texture->currentmaterialflags);
9803                                 end = start + 1;
9804                                 continue;
9805                         }
9806                         for (end = start + 1;end < texturenumsurfaces && startplaneindex == RSurf_FindWaterPlaneForSurface(texturesurfacelist[end]);end++)
9807                                 ;
9808                         // now that we have a batch using the same planeindex, render it
9809                         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION | MATERIALFLAG_CAMERA)))
9810                         {
9811                                 // render water or distortion background
9812                                 GL_DepthMask(true);
9813                                 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);
9814                                 RSurf_DrawBatch();
9815                                 // blend surface on top
9816                                 GL_DepthMask(false);
9817                                 R_SetupShader_Surface(vec3_origin, (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT) != 0, 1, 1, rsurface.texture->specularscale, RSURFPASS_BASE, end-start, texturesurfacelist + start, NULL, false);
9818                                 RSurf_DrawBatch();
9819                         }
9820                         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_REFLECTION))
9821                         {
9822                                 // render surface with reflection texture as input
9823                                 GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9824                                 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);
9825                                 RSurf_DrawBatch();
9826                         }
9827                 }
9828                 return;
9829         }
9830
9831         // render surface batch normally
9832         GL_DepthMask(writedepth && !(rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED));
9833         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);
9834         RSurf_DrawBatch();
9835 }
9836
9837 static void R_DrawTextureSurfaceList_GL13(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9838 {
9839         // OpenGL 1.3 path - anything not completely ancient
9840         qboolean applycolor;
9841         qboolean applyfog;
9842         int layerindex;
9843         const texturelayer_t *layer;
9844         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);
9845         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9846
9847         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9848         {
9849                 vec4_t layercolor;
9850                 int layertexrgbscale;
9851                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9852                 {
9853                         if (layerindex == 0)
9854                                 GL_AlphaTest(true);
9855                         else
9856                         {
9857                                 GL_AlphaTest(false);
9858                                 GL_DepthFunc(GL_EQUAL);
9859                         }
9860                 }
9861                 GL_DepthMask(layer->depthmask && writedepth);
9862                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9863                 if (layer->color[0] > 2 || layer->color[1] > 2 || layer->color[2] > 2)
9864                 {
9865                         layertexrgbscale = 4;
9866                         VectorScale(layer->color, 0.25f, layercolor);
9867                 }
9868                 else if (layer->color[0] > 1 || layer->color[1] > 1 || layer->color[2] > 1)
9869                 {
9870                         layertexrgbscale = 2;
9871                         VectorScale(layer->color, 0.5f, layercolor);
9872                 }
9873                 else
9874                 {
9875                         layertexrgbscale = 1;
9876                         VectorScale(layer->color, 1.0f, layercolor);
9877                 }
9878                 layercolor[3] = layer->color[3];
9879                 applycolor = layercolor[0] != 1 || layercolor[1] != 1 || layercolor[2] != 1 || layercolor[3] != 1;
9880                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9881                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9882                 switch (layer->type)
9883                 {
9884                 case TEXTURELAYERTYPE_LITTEXTURE:
9885                         // single-pass lightmapped texture with 2x rgbscale
9886                         R_Mesh_TexBind(0, r_texture_white);
9887                         R_Mesh_TexMatrix(0, NULL);
9888                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9889                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9890                         R_Mesh_TexBind(1, layer->texture);
9891                         R_Mesh_TexMatrix(1, &layer->texmatrix);
9892                         R_Mesh_TexCombine(1, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9893                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9894                         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9895                                 RSurf_DrawBatch_GL11_VertexShade(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9896                         else if (FAKELIGHT_ENABLED)
9897                                 RSurf_DrawBatch_GL11_FakeLight(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9898                         else if (rsurface.uselightmaptexture)
9899                                 RSurf_DrawBatch_GL11_Lightmap(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9900                         else
9901                                 RSurf_DrawBatch_GL11_VertexColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9902                         break;
9903                 case TEXTURELAYERTYPE_TEXTURE:
9904                         // singletexture unlit texture with transparency support
9905                         R_Mesh_TexBind(0, layer->texture);
9906                         R_Mesh_TexMatrix(0, &layer->texmatrix);
9907                         R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9908                         R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9909                         R_Mesh_TexBind(1, 0);
9910                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9911                         RSurf_DrawBatch_GL11_Unlit(layercolor[0], layercolor[1], layercolor[2], layercolor[3], applycolor, applyfog);
9912                         break;
9913                 case TEXTURELAYERTYPE_FOG:
9914                         // singletexture fogging
9915                         if (layer->texture)
9916                         {
9917                                 R_Mesh_TexBind(0, layer->texture);
9918                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9919                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, layertexrgbscale, 1);
9920                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9921                         }
9922                         else
9923                         {
9924                                 R_Mesh_TexBind(0, 0);
9925                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9926                         }
9927                         R_Mesh_TexBind(1, 0);
9928                         R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
9929                         // generate a color array for the fog pass
9930                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
9931                         RSurf_DrawBatch_GL11_MakeFogColor(layercolor[0], layercolor[1], layercolor[2], layercolor[3]);
9932                         RSurf_DrawBatch();
9933                         break;
9934                 default:
9935                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
9936                 }
9937         }
9938         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9939         {
9940                 GL_DepthFunc(GL_LEQUAL);
9941                 GL_AlphaTest(false);
9942         }
9943 }
9944
9945 static void R_DrawTextureSurfaceList_GL11(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
9946 {
9947         // OpenGL 1.1 - crusty old voodoo path
9948         qboolean applyfog;
9949         int layerindex;
9950         const texturelayer_t *layer;
9951         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);
9952         R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer, rsurface.batchvertex3f_bufferoffset);
9953
9954         for (layerindex = 0, layer = rsurface.texture->currentlayers;layerindex < rsurface.texture->currentnumlayers;layerindex++, layer++)
9955         {
9956                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
9957                 {
9958                         if (layerindex == 0)
9959                                 GL_AlphaTest(true);
9960                         else
9961                         {
9962                                 GL_AlphaTest(false);
9963                                 GL_DepthFunc(GL_EQUAL);
9964                         }
9965                 }
9966                 GL_DepthMask(layer->depthmask && writedepth);
9967                 GL_BlendFunc(layer->blendfunc1, layer->blendfunc2);
9968                 R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, 0, 0);
9969                 applyfog = r_refdef.fogenabled && (rsurface.texture->currentmaterialflags & MATERIALFLAG_BLENDED);
9970                 switch (layer->type)
9971                 {
9972                 case TEXTURELAYERTYPE_LITTEXTURE:
9973                         if (layer->blendfunc1 == GL_ONE && layer->blendfunc2 == GL_ZERO)
9974                         {
9975                                 // two-pass lit texture with 2x rgbscale
9976                                 // first the lightmap pass
9977                                 R_Mesh_TexBind(0, r_texture_white);
9978                                 R_Mesh_TexMatrix(0, NULL);
9979                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9980                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordlightmap2f, rsurface.batchtexcoordlightmap2f_vertexbuffer, rsurface.batchtexcoordlightmap2f_bufferoffset);
9981                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
9982                                         RSurf_DrawBatch_GL11_VertexShade(1, 1, 1, 1, false, false);
9983                                 else if (FAKELIGHT_ENABLED)
9984                                         RSurf_DrawBatch_GL11_FakeLight(1, 1, 1, 1, false, false);
9985                                 else if (rsurface.uselightmaptexture)
9986                                         RSurf_DrawBatch_GL11_Lightmap(1, 1, 1, 1, false, false);
9987                                 else
9988                                         RSurf_DrawBatch_GL11_VertexColor(1, 1, 1, 1, false, false);
9989                                 // then apply the texture to it
9990                                 GL_BlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
9991                                 R_Mesh_TexBind(0, layer->texture);
9992                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
9993                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
9994                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
9995                                 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);
9996                         }
9997                         else
9998                         {
9999                                 // single pass vertex-lighting-only texture with 1x rgbscale and transparency support
10000                                 R_Mesh_TexBind(0, layer->texture);
10001                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10002                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10003                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10004                                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10005                                         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);
10006                                 else
10007                                         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);
10008                         }
10009                         break;
10010                 case TEXTURELAYERTYPE_TEXTURE:
10011                         // singletexture unlit texture with transparency support
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                         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);
10017                         break;
10018                 case TEXTURELAYERTYPE_FOG:
10019                         // singletexture fogging
10020                         if (layer->texture)
10021                         {
10022                                 R_Mesh_TexBind(0, layer->texture);
10023                                 R_Mesh_TexMatrix(0, &layer->texmatrix);
10024                                 R_Mesh_TexCombine(0, GL_MODULATE, GL_MODULATE, 1, 1);
10025                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), rsurface.batchtexcoordtexture2f, rsurface.batchtexcoordtexture2f_vertexbuffer, rsurface.batchtexcoordtexture2f_bufferoffset);
10026                         }
10027                         else
10028                         {
10029                                 R_Mesh_TexBind(0, 0);
10030                                 R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, 0, 0);
10031                         }
10032                         // generate a color array for the fog pass
10033                         R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), rsurface.passcolor4f, 0, 0);
10034                         RSurf_DrawBatch_GL11_MakeFogColor(layer->color[0], layer->color[1], layer->color[2], layer->color[3]);
10035                         RSurf_DrawBatch();
10036                         break;
10037                 default:
10038                         Con_Printf("R_DrawTextureSurfaceList: unknown layer type %i\n", layer->type);
10039                 }
10040         }
10041         if (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10042         {
10043                 GL_DepthFunc(GL_LEQUAL);
10044                 GL_AlphaTest(false);
10045         }
10046 }
10047
10048 static void R_DrawTextureSurfaceList_ShowSurfaces(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth)
10049 {
10050         int vi;
10051         int j;
10052         r_vertexgeneric_t *batchvertex;
10053         float c[4];
10054
10055 //      R_Mesh_ResetTextureState();
10056         R_SetupShader_Generic_NoTexture(false, false);
10057
10058         if(rsurface.texture && rsurface.texture->currentskinframe)
10059         {
10060                 memcpy(c, rsurface.texture->currentskinframe->avgcolor, sizeof(c));
10061                 c[3] *= rsurface.texture->currentalpha;
10062         }
10063         else
10064         {
10065                 c[0] = 1;
10066                 c[1] = 0;
10067                 c[2] = 1;
10068                 c[3] = 1;
10069         }
10070
10071         if (rsurface.texture->pantstexture || rsurface.texture->shirttexture)
10072         {
10073                 c[0] = 0.5 * (rsurface.colormap_pantscolor[0] * 0.3 + rsurface.colormap_shirtcolor[0] * 0.7);
10074                 c[1] = 0.5 * (rsurface.colormap_pantscolor[1] * 0.3 + rsurface.colormap_shirtcolor[1] * 0.7);
10075                 c[2] = 0.5 * (rsurface.colormap_pantscolor[2] * 0.3 + rsurface.colormap_shirtcolor[2] * 0.7);
10076         }
10077
10078         // brighten it up (as texture value 127 means "unlit")
10079         c[0] *= 2 * r_refdef.view.colorscale;
10080         c[1] *= 2 * r_refdef.view.colorscale;
10081         c[2] *= 2 * r_refdef.view.colorscale;
10082
10083         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_WATERALPHA)
10084                 c[3] *= r_wateralpha.value;
10085
10086         if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHA && c[3] != 1)
10087         {
10088                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10089                 GL_DepthMask(false);
10090         }
10091         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ADD)
10092         {
10093                 GL_BlendFunc(GL_ONE, GL_ONE);
10094                 GL_DepthMask(false);
10095         }
10096         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST)
10097         {
10098                 GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // can't do alpha test without texture, so let's blend instead
10099                 GL_DepthMask(false);
10100         }
10101         else if(rsurface.texture->currentmaterialflags & MATERIALFLAG_CUSTOMBLEND)
10102         {
10103                 GL_BlendFunc(rsurface.texture->customblendfunc[0], rsurface.texture->customblendfunc[1]);
10104                 GL_DepthMask(false);
10105         }
10106         else
10107         {
10108                 GL_BlendFunc(GL_ONE, GL_ZERO);
10109                 GL_DepthMask(writedepth);
10110         }
10111
10112         if (r_showsurfaces.integer == 3)
10113         {
10114                 rsurface.passcolor4f = NULL;
10115
10116                 if (rsurface.texture->currentmaterialflags & MATERIALFLAG_FULLBRIGHT)
10117                 {
10118                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10119
10120                         rsurface.passcolor4f = NULL;
10121                         rsurface.passcolor4f_vertexbuffer = 0;
10122                         rsurface.passcolor4f_bufferoffset = 0;
10123                 }
10124                 else if (rsurface.texture->currentmaterialflags & MATERIALFLAG_MODELLIGHT)
10125                 {
10126                         qboolean applycolor = true;
10127                         float one = 1.0;
10128
10129                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10130
10131                         r_refdef.lightmapintensity = 1;
10132                         RSurf_DrawBatch_GL11_ApplyVertexShade(&one, &one, &one, &one, &applycolor);
10133                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10134                 }
10135                 else if (FAKELIGHT_ENABLED)
10136                 {
10137                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10138
10139                         r_refdef.lightmapintensity = r_fakelight_intensity.value;
10140                         RSurf_DrawBatch_GL11_ApplyFakeLight();
10141                         r_refdef.lightmapintensity = 0; // we're in showsurfaces, after all
10142                 }
10143                 else
10144                 {
10145                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_VERTEXCOLOR | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10146
10147                         rsurface.passcolor4f = rsurface.batchlightmapcolor4f;
10148                         rsurface.passcolor4f_vertexbuffer = rsurface.batchlightmapcolor4f_vertexbuffer;
10149                         rsurface.passcolor4f_bufferoffset = rsurface.batchlightmapcolor4f_bufferoffset;
10150                 }
10151
10152                 if(!rsurface.passcolor4f)
10153                         RSurf_DrawBatch_GL11_MakeFullbrightLightmapColorArray();
10154
10155                 RSurf_DrawBatch_GL11_ApplyAmbient();
10156                 RSurf_DrawBatch_GL11_ApplyColor(c[0], c[1], c[2], c[3]);
10157                 if(r_refdef.fogenabled)
10158                         RSurf_DrawBatch_GL11_ApplyFogToFinishedVertexColors();
10159                 RSurf_DrawBatch_GL11_ClampColor();
10160
10161                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.passcolor4f, NULL);
10162                 R_SetupShader_Generic_NoTexture(false, false);
10163                 RSurf_DrawBatch();
10164         }
10165         else if (!r_refdef.view.showdebug)
10166         {
10167                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10168                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10169                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10170                 {
10171                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10172                         Vector4Set(batchvertex[vi].color4f, 0, 0, 0, 1);
10173                 }
10174                 R_Mesh_PrepareVertices_Generic_Unlock();
10175                 RSurf_DrawBatch();
10176         }
10177         else if (r_showsurfaces.integer == 4)
10178         {
10179                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10180                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchnumvertices);
10181                 for (j = 0, vi = rsurface.batchfirstvertex;j < rsurface.batchnumvertices;j++, vi++)
10182                 {
10183                         unsigned char c = (vi << 3) * (1.0f / 256.0f);
10184                         VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10185                         Vector4Set(batchvertex[vi].color4f, c, c, c, 1);
10186                 }
10187                 R_Mesh_PrepareVertices_Generic_Unlock();
10188                 RSurf_DrawBatch();
10189         }
10190         else if (r_showsurfaces.integer == 2)
10191         {
10192                 const int *e;
10193                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10194                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(3*rsurface.batchnumtriangles);
10195                 for (j = 0, e = rsurface.batchelement3i + 3 * rsurface.batchfirsttriangle;j < rsurface.batchnumtriangles;j++, e += 3)
10196                 {
10197                         unsigned char c = ((j + rsurface.batchfirsttriangle) << 3) * (1.0f / 256.0f);
10198                         VectorCopy(rsurface.batchvertex3f + 3*e[0], batchvertex[j*3+0].vertex3f);
10199                         VectorCopy(rsurface.batchvertex3f + 3*e[1], batchvertex[j*3+1].vertex3f);
10200                         VectorCopy(rsurface.batchvertex3f + 3*e[2], batchvertex[j*3+2].vertex3f);
10201                         Vector4Set(batchvertex[j*3+0].color4f, c, c, c, 1);
10202                         Vector4Set(batchvertex[j*3+1].color4f, c, c, c, 1);
10203                         Vector4Set(batchvertex[j*3+2].color4f, c, c, c, 1);
10204                 }
10205                 R_Mesh_PrepareVertices_Generic_Unlock();
10206                 R_Mesh_Draw(0, rsurface.batchnumtriangles*3, 0, rsurface.batchnumtriangles, NULL, NULL, 0, NULL, NULL, 0);
10207         }
10208         else
10209         {
10210                 int texturesurfaceindex;
10211                 int k;
10212                 const msurface_t *surface;
10213                 float surfacecolor4f[4];
10214                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, texturenumsurfaces, texturesurfacelist);
10215                 batchvertex = R_Mesh_PrepareVertices_Generic_Lock(rsurface.batchfirstvertex + rsurface.batchnumvertices);
10216                 vi = 0;
10217                 for (texturesurfaceindex = 0;texturesurfaceindex < texturenumsurfaces;texturesurfaceindex++)
10218                 {
10219                         surface = texturesurfacelist[texturesurfaceindex];
10220                         k = (int)(((size_t)surface) / sizeof(msurface_t));
10221                         Vector4Set(surfacecolor4f, (k & 0xF) * (1.0f / 16.0f), (k & 0xF0) * (1.0f / 256.0f), (k & 0xF00) * (1.0f / 4096.0f), 1);
10222                         for (j = 0;j < surface->num_vertices;j++)
10223                         {
10224                                 VectorCopy(rsurface.batchvertex3f + 3*vi, batchvertex[vi].vertex3f);
10225                                 Vector4Copy(surfacecolor4f, batchvertex[vi].color4f);
10226                                 vi++;
10227                         }
10228                 }
10229                 R_Mesh_PrepareVertices_Generic_Unlock();
10230                 RSurf_DrawBatch();
10231         }
10232 }
10233
10234 static void R_DrawWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10235 {
10236         CHECKGLERROR
10237         RSurf_SetupDepthAndCulling();
10238         if (r_showsurfaces.integer)
10239         {
10240                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10241                 return;
10242         }
10243         switch (vid.renderpath)
10244         {
10245         case RENDERPATH_GL20:
10246         case RENDERPATH_D3D9:
10247         case RENDERPATH_D3D10:
10248         case RENDERPATH_D3D11:
10249         case RENDERPATH_SOFT:
10250         case RENDERPATH_GLES2:
10251                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10252                 break;
10253         case RENDERPATH_GL13:
10254         case RENDERPATH_GLES1:
10255                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10256                 break;
10257         case RENDERPATH_GL11:
10258                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10259                 break;
10260         }
10261         CHECKGLERROR
10262 }
10263
10264 static void R_DrawModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean prepass)
10265 {
10266         CHECKGLERROR
10267         RSurf_SetupDepthAndCulling();
10268         if (r_showsurfaces.integer)
10269         {
10270                 R_DrawTextureSurfaceList_ShowSurfaces(texturenumsurfaces, texturesurfacelist, writedepth);
10271                 return;
10272         }
10273         switch (vid.renderpath)
10274         {
10275         case RENDERPATH_GL20:
10276         case RENDERPATH_D3D9:
10277         case RENDERPATH_D3D10:
10278         case RENDERPATH_D3D11:
10279         case RENDERPATH_SOFT:
10280         case RENDERPATH_GLES2:
10281                 R_DrawTextureSurfaceList_GL20(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10282                 break;
10283         case RENDERPATH_GL13:
10284         case RENDERPATH_GLES1:
10285                 R_DrawTextureSurfaceList_GL13(texturenumsurfaces, texturesurfacelist, writedepth);
10286                 break;
10287         case RENDERPATH_GL11:
10288                 R_DrawTextureSurfaceList_GL11(texturenumsurfaces, texturesurfacelist, writedepth);
10289                 break;
10290         }
10291         CHECKGLERROR
10292 }
10293
10294 static void R_DrawSurface_TransparentCallback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10295 {
10296         int i, j;
10297         int texturenumsurfaces, endsurface;
10298         texture_t *texture;
10299         const msurface_t *surface;
10300         const msurface_t *texturesurfacelist[MESHQUEUE_TRANSPARENT_BATCHSIZE];
10301
10302         // if the model is static it doesn't matter what value we give for
10303         // wantnormals and wanttangents, so this logic uses only rules applicable
10304         // to a model, knowing that they are meaningless otherwise
10305         if (ent == r_refdef.scene.worldentity)
10306                 RSurf_ActiveWorldEntity();
10307         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
10308                 RSurf_ActiveModelEntity(ent, false, false, false);
10309         else
10310         {
10311                 switch (vid.renderpath)
10312                 {
10313                 case RENDERPATH_GL20:
10314                 case RENDERPATH_D3D9:
10315                 case RENDERPATH_D3D10:
10316                 case RENDERPATH_D3D11:
10317                 case RENDERPATH_SOFT:
10318                 case RENDERPATH_GLES2:
10319                         RSurf_ActiveModelEntity(ent, true, true, false);
10320                         break;
10321                 case RENDERPATH_GL11:
10322                 case RENDERPATH_GL13:
10323                 case RENDERPATH_GLES1:
10324                         RSurf_ActiveModelEntity(ent, true, false, false);
10325                         break;
10326                 }
10327         }
10328
10329         if (r_transparentdepthmasking.integer)
10330         {
10331                 qboolean setup = false;
10332                 for (i = 0;i < numsurfaces;i = j)
10333                 {
10334                         j = i + 1;
10335                         surface = rsurface.modelsurfaces + surfacelist[i];
10336                         texture = surface->texture;
10337                         rsurface.texture = R_GetCurrentTexture(texture);
10338                         rsurface.lightmaptexture = NULL;
10339                         rsurface.deluxemaptexture = NULL;
10340                         rsurface.uselightmaptexture = false;
10341                         // scan ahead until we find a different texture
10342                         endsurface = min(i + 1024, numsurfaces);
10343                         texturenumsurfaces = 0;
10344                         texturesurfacelist[texturenumsurfaces++] = surface;
10345                         for (;j < endsurface;j++)
10346                         {
10347                                 surface = rsurface.modelsurfaces + surfacelist[j];
10348                                 if (texture != surface->texture)
10349                                         break;
10350                                 texturesurfacelist[texturenumsurfaces++] = surface;
10351                         }
10352                         if (!(rsurface.texture->currentmaterialflags & MATERIALFLAG_TRANSDEPTH))
10353                                 continue;
10354                         // render the range of surfaces as depth
10355                         if (!setup)
10356                         {
10357                                 setup = true;
10358                                 GL_ColorMask(0,0,0,0);
10359                                 GL_Color(1,1,1,1);
10360                                 GL_DepthTest(true);
10361                                 GL_BlendFunc(GL_ONE, GL_ZERO);
10362                                 GL_DepthMask(true);
10363 //                              R_Mesh_ResetTextureState();
10364                                 R_SetupShader_DepthOrShadow(false, false);
10365                         }
10366                         RSurf_SetupDepthAndCulling();
10367                         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10368                         if (rsurface.batchvertex3fbuffer)
10369                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10370                         else
10371                                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10372                         RSurf_DrawBatch();
10373                 }
10374                 if (setup)
10375                         GL_ColorMask(r_refdef.view.colormask[0], r_refdef.view.colormask[1], r_refdef.view.colormask[2], 1);
10376         }
10377
10378         for (i = 0;i < numsurfaces;i = j)
10379         {
10380                 j = i + 1;
10381                 surface = rsurface.modelsurfaces + surfacelist[i];
10382                 texture = surface->texture;
10383                 rsurface.texture = R_GetCurrentTexture(texture);
10384                 // scan ahead until we find a different texture
10385                 endsurface = min(i + MESHQUEUE_TRANSPARENT_BATCHSIZE, numsurfaces);
10386                 texturenumsurfaces = 0;
10387                 texturesurfacelist[texturenumsurfaces++] = surface;
10388                 if(FAKELIGHT_ENABLED)
10389                 {
10390                         rsurface.lightmaptexture = NULL;
10391                         rsurface.deluxemaptexture = NULL;
10392                         rsurface.uselightmaptexture = false;
10393                         for (;j < endsurface;j++)
10394                         {
10395                                 surface = rsurface.modelsurfaces + surfacelist[j];
10396                                 if (texture != surface->texture)
10397                                         break;
10398                                 texturesurfacelist[texturenumsurfaces++] = surface;
10399                         }
10400                 }
10401                 else
10402                 {
10403                         rsurface.lightmaptexture = surface->lightmaptexture;
10404                         rsurface.deluxemaptexture = surface->deluxemaptexture;
10405                         rsurface.uselightmaptexture = surface->lightmaptexture != NULL;
10406                         for (;j < endsurface;j++)
10407                         {
10408                                 surface = rsurface.modelsurfaces + surfacelist[j];
10409                                 if (texture != surface->texture || rsurface.lightmaptexture != surface->lightmaptexture)
10410                                         break;
10411                                 texturesurfacelist[texturenumsurfaces++] = surface;
10412                         }
10413                 }
10414                 // render the range of surfaces
10415                 if (ent == r_refdef.scene.worldentity)
10416                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10417                 else
10418                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, false, false);
10419         }
10420         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
10421 }
10422
10423 static void R_ProcessTransparentTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10424 {
10425         // transparent surfaces get pushed off into the transparent queue
10426         int surfacelistindex;
10427         const msurface_t *surface;
10428         vec3_t tempcenter, center;
10429         for (surfacelistindex = 0;surfacelistindex < texturenumsurfaces;surfacelistindex++)
10430         {
10431                 surface = texturesurfacelist[surfacelistindex];
10432                 if (r_transparent_sortsurfacesbynearest.integer)
10433                 {
10434                         tempcenter[0] = bound(surface->mins[0], rsurface.localvieworigin[0], surface->maxs[0]);
10435                         tempcenter[1] = bound(surface->mins[1], rsurface.localvieworigin[1], surface->maxs[1]);
10436                         tempcenter[2] = bound(surface->mins[2], rsurface.localvieworigin[2], surface->maxs[2]);
10437                 }
10438                 else
10439                 {
10440                         tempcenter[0] = (surface->mins[0] + surface->maxs[0]) * 0.5f;
10441                         tempcenter[1] = (surface->mins[1] + surface->maxs[1]) * 0.5f;
10442                         tempcenter[2] = (surface->mins[2] + surface->maxs[2]) * 0.5f;
10443                 }
10444                 Matrix4x4_Transform(&rsurface.matrix, tempcenter, center);
10445                 if (rsurface.entity->transparent_offset) // transparent offset
10446                 {
10447                         center[0] += r_refdef.view.forward[0]*rsurface.entity->transparent_offset;
10448                         center[1] += r_refdef.view.forward[1]*rsurface.entity->transparent_offset;
10449                         center[2] += r_refdef.view.forward[2]*rsurface.entity->transparent_offset;
10450                 }
10451                 R_MeshQueue_AddTransparent((rsurface.texture->currentmaterialflags & MATERIALFLAG_NODEPTHTEST) ? MESHQUEUE_SORT_HUD : ((rsurface.entity->flags & RENDER_WORLDOBJECT) ? MESHQUEUE_SORT_SKY : MESHQUEUE_SORT_DISTANCE), center, R_DrawSurface_TransparentCallback, rsurface.entity, surface - rsurface.modelsurfaces, rsurface.rtlight);
10452         }
10453 }
10454
10455 static void R_DrawTextureSurfaceList_DepthOnly(int texturenumsurfaces, const msurface_t **texturesurfacelist)
10456 {
10457         if ((rsurface.texture->currentmaterialflags & (MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_BLENDED | MATERIALFLAG_ALPHATEST)))
10458                 return;
10459         if (r_fb.water.renderingscene && (rsurface.texture->currentmaterialflags & (MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFLECTION)))
10460                 return;
10461         RSurf_SetupDepthAndCulling();
10462         RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX, texturenumsurfaces, texturesurfacelist);
10463         if (rsurface.batchvertex3fbuffer)
10464                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3fbuffer);
10465         else
10466                 R_Mesh_PrepareVertices_Vertex3f(rsurface.batchnumvertices, rsurface.batchvertex3f, rsurface.batchvertex3f_vertexbuffer);
10467         RSurf_DrawBatch();
10468 }
10469
10470 static void R_ProcessWorldTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10471 {
10472         CHECKGLERROR
10473         if (depthonly)
10474                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10475         else if (prepass)
10476         {
10477                 if (!rsurface.texture->currentnumlayers)
10478                         return;
10479                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10480                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10481                 else
10482                         R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10483         }
10484         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10485                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10486         else if (!rsurface.texture->currentnumlayers)
10487                 return;
10488         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10489         {
10490                 // in the deferred case, transparent surfaces were queued during prepass
10491                 if (!r_shadow_usingdeferredprepass)
10492                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10493         }
10494         else
10495         {
10496                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10497                 R_DrawWorldTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10498         }
10499         CHECKGLERROR
10500 }
10501
10502 static void R_QueueWorldSurfaceList(int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10503 {
10504         int i, j;
10505         texture_t *texture;
10506         R_FrameData_SetMark();
10507         // break the surface list down into batches by texture and use of lightmapping
10508         for (i = 0;i < numsurfaces;i = j)
10509         {
10510                 j = i + 1;
10511                 // texture is the base texture pointer, rsurface.texture is the
10512                 // current frame/skin the texture is directing us to use (for example
10513                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10514                 // use skin 1 instead)
10515                 texture = surfacelist[i]->texture;
10516                 rsurface.texture = R_GetCurrentTexture(texture);
10517                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10518                 {
10519                         // if this texture is not the kind we want, skip ahead to the next one
10520                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10521                                 ;
10522                         continue;
10523                 }
10524                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10525                 {
10526                         rsurface.lightmaptexture = NULL;
10527                         rsurface.deluxemaptexture = NULL;
10528                         rsurface.uselightmaptexture = false;
10529                         // simply scan ahead until we find a different texture or lightmap state
10530                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10531                                 ;
10532                 }
10533                 else
10534                 {
10535                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10536                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10537                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10538                         // simply scan ahead until we find a different texture or lightmap state
10539                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10540                                 ;
10541                 }
10542                 // render the range of surfaces
10543                 R_ProcessWorldTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10544         }
10545         R_FrameData_ReturnToMark();
10546 }
10547
10548 static void R_ProcessModelTextureSurfaceList(int texturenumsurfaces, const msurface_t **texturesurfacelist, qboolean writedepth, qboolean depthonly, qboolean prepass)
10549 {
10550         CHECKGLERROR
10551         if (depthonly)
10552                 R_DrawTextureSurfaceList_DepthOnly(texturenumsurfaces, texturesurfacelist);
10553         else if (prepass)
10554         {
10555                 if (!rsurface.texture->currentnumlayers)
10556                         return;
10557                 if (rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED)
10558                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10559                 else
10560                         R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth, prepass);
10561         }
10562         else if ((rsurface.texture->currentmaterialflags & MATERIALFLAG_SKY) && (!r_showsurfaces.integer || r_showsurfaces.integer == 3))
10563                 R_DrawTextureSurfaceList_Sky(texturenumsurfaces, texturesurfacelist);
10564         else if (!rsurface.texture->currentnumlayers)
10565                 return;
10566         else if (((rsurface.texture->currentmaterialflags & MATERIALFLAGMASK_DEPTHSORTED) || (r_showsurfaces.integer == 3 && (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST))))
10567         {
10568                 // in the deferred case, transparent surfaces were queued during prepass
10569                 if (!r_shadow_usingdeferredprepass)
10570                         R_ProcessTransparentTextureSurfaceList(texturenumsurfaces, texturesurfacelist);
10571         }
10572         else
10573         {
10574                 // the alphatest check is to make sure we write depth for anything we skipped on the depth-only pass earlier
10575                 R_DrawModelTextureSurfaceList(texturenumsurfaces, texturesurfacelist, writedepth || (rsurface.texture->currentmaterialflags & MATERIALFLAG_ALPHATEST), prepass);
10576         }
10577         CHECKGLERROR
10578 }
10579
10580 static void R_QueueModelSurfaceList(entity_render_t *ent, int numsurfaces, const msurface_t **surfacelist, int flagsmask, qboolean writedepth, qboolean depthonly, qboolean prepass)
10581 {
10582         int i, j;
10583         texture_t *texture;
10584         R_FrameData_SetMark();
10585         // break the surface list down into batches by texture and use of lightmapping
10586         for (i = 0;i < numsurfaces;i = j)
10587         {
10588                 j = i + 1;
10589                 // texture is the base texture pointer, rsurface.texture is the
10590                 // current frame/skin the texture is directing us to use (for example
10591                 // if a model has 2 skins and it is on skin 1, then skin 0 tells us to
10592                 // use skin 1 instead)
10593                 texture = surfacelist[i]->texture;
10594                 rsurface.texture = R_GetCurrentTexture(texture);
10595                 if (!(rsurface.texture->currentmaterialflags & flagsmask) || (rsurface.texture->currentmaterialflags & MATERIALFLAG_NODRAW))
10596                 {
10597                         // if this texture is not the kind we want, skip ahead to the next one
10598                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10599                                 ;
10600                         continue;
10601                 }
10602                 if(FAKELIGHT_ENABLED || depthonly || prepass)
10603                 {
10604                         rsurface.lightmaptexture = NULL;
10605                         rsurface.deluxemaptexture = NULL;
10606                         rsurface.uselightmaptexture = false;
10607                         // simply scan ahead until we find a different texture or lightmap state
10608                         for (;j < numsurfaces && texture == surfacelist[j]->texture;j++)
10609                                 ;
10610                 }
10611                 else
10612                 {
10613                         rsurface.lightmaptexture = surfacelist[i]->lightmaptexture;
10614                         rsurface.deluxemaptexture = surfacelist[i]->deluxemaptexture;
10615                         rsurface.uselightmaptexture = surfacelist[i]->lightmaptexture != NULL;
10616                         // simply scan ahead until we find a different texture or lightmap state
10617                         for (;j < numsurfaces && texture == surfacelist[j]->texture && rsurface.lightmaptexture == surfacelist[j]->lightmaptexture;j++)
10618                                 ;
10619                 }
10620                 // render the range of surfaces
10621                 R_ProcessModelTextureSurfaceList(j - i, surfacelist + i, writedepth, depthonly, prepass);
10622         }
10623         R_FrameData_ReturnToMark();
10624 }
10625
10626 float locboxvertex3f[6*4*3] =
10627 {
10628         1,0,1, 1,0,0, 1,1,0, 1,1,1,
10629         0,1,1, 0,1,0, 0,0,0, 0,0,1,
10630         1,1,1, 1,1,0, 0,1,0, 0,1,1,
10631         0,0,1, 0,0,0, 1,0,0, 1,0,1,
10632         0,0,1, 1,0,1, 1,1,1, 0,1,1,
10633         1,0,0, 0,0,0, 0,1,0, 1,1,0
10634 };
10635
10636 unsigned short locboxelements[6*2*3] =
10637 {
10638          0, 1, 2, 0, 2, 3,
10639          4, 5, 6, 4, 6, 7,
10640          8, 9,10, 8,10,11,
10641         12,13,14, 12,14,15,
10642         16,17,18, 16,18,19,
10643         20,21,22, 20,22,23
10644 };
10645
10646 static void R_DrawLoc_Callback(const entity_render_t *ent, const rtlight_t *rtlight, int numsurfaces, int *surfacelist)
10647 {
10648         int i, j;
10649         cl_locnode_t *loc = (cl_locnode_t *)ent;
10650         vec3_t mins, size;
10651         float vertex3f[6*4*3];
10652         CHECKGLERROR
10653         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
10654         GL_DepthMask(false);
10655         GL_DepthRange(0, 1);
10656         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
10657         GL_DepthTest(true);
10658         GL_CullFace(GL_NONE);
10659         R_EntityMatrix(&identitymatrix);
10660
10661 //      R_Mesh_ResetTextureState();
10662
10663         i = surfacelist[0];
10664         GL_Color(((i & 0x0007) >> 0) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10665                          ((i & 0x0038) >> 3) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10666                          ((i & 0x01C0) >> 6) * (1.0f / 7.0f) * r_refdef.view.colorscale,
10667                         surfacelist[0] < 0 ? 0.5f : 0.125f);
10668
10669         if (VectorCompare(loc->mins, loc->maxs))
10670         {
10671                 VectorSet(size, 2, 2, 2);
10672                 VectorMA(loc->mins, -0.5f, size, mins);
10673         }
10674         else
10675         {
10676                 VectorCopy(loc->mins, mins);
10677                 VectorSubtract(loc->maxs, loc->mins, size);
10678         }
10679
10680         for (i = 0;i < 6*4*3;)
10681                 for (j = 0;j < 3;j++, i++)
10682                         vertex3f[i] = mins[j] + size[j] * locboxvertex3f[i];
10683
10684         R_Mesh_PrepareVertices_Generic_Arrays(6*4, vertex3f, NULL, NULL);
10685         R_SetupShader_Generic_NoTexture(false, false);
10686         R_Mesh_Draw(0, 6*4, 0, 6*2, NULL, NULL, 0, locboxelements, NULL, 0);
10687 }
10688
10689 void R_DrawLocs(void)
10690 {
10691         int index;
10692         cl_locnode_t *loc, *nearestloc;
10693         vec3_t center;
10694         nearestloc = CL_Locs_FindNearest(cl.movement_origin);
10695         for (loc = cl.locnodes, index = 0;loc;loc = loc->next, index++)
10696         {
10697                 VectorLerp(loc->mins, 0.5f, loc->maxs, center);
10698                 R_MeshQueue_AddTransparent(MESHQUEUE_SORT_DISTANCE, center, R_DrawLoc_Callback, (entity_render_t *)loc, loc == nearestloc ? -1 : index, NULL);
10699         }
10700 }
10701
10702 void R_DecalSystem_Reset(decalsystem_t *decalsystem)
10703 {
10704         if (decalsystem->decals)
10705                 Mem_Free(decalsystem->decals);
10706         memset(decalsystem, 0, sizeof(*decalsystem));
10707 }
10708
10709 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)
10710 {
10711         tridecal_t *decal;
10712         tridecal_t *decals;
10713         int i;
10714
10715         // expand or initialize the system
10716         if (decalsystem->maxdecals <= decalsystem->numdecals)
10717         {
10718                 decalsystem_t old = *decalsystem;
10719                 qboolean useshortelements;
10720                 decalsystem->maxdecals = max(16, decalsystem->maxdecals * 2);
10721                 useshortelements = decalsystem->maxdecals * 3 <= 65536;
10722                 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)));
10723                 decalsystem->color4f = (float *)(decalsystem->decals + decalsystem->maxdecals);
10724                 decalsystem->texcoord2f = (float *)(decalsystem->color4f + decalsystem->maxdecals*12);
10725                 decalsystem->vertex3f = (float *)(decalsystem->texcoord2f + decalsystem->maxdecals*6);
10726                 decalsystem->element3i = (int *)(decalsystem->vertex3f + decalsystem->maxdecals*9);
10727                 decalsystem->element3s = (useshortelements ? ((unsigned short *)(decalsystem->element3i + decalsystem->maxdecals*3)) : NULL);
10728                 if (decalsystem->numdecals)
10729                         memcpy(decalsystem->decals, old.decals, decalsystem->numdecals * sizeof(tridecal_t));
10730                 if (old.decals)
10731                         Mem_Free(old.decals);
10732                 for (i = 0;i < decalsystem->maxdecals*3;i++)
10733                         decalsystem->element3i[i] = i;
10734                 if (useshortelements)
10735                         for (i = 0;i < decalsystem->maxdecals*3;i++)
10736                                 decalsystem->element3s[i] = i;
10737         }
10738
10739         // grab a decal and search for another free slot for the next one
10740         decals = decalsystem->decals;
10741         decal = decalsystem->decals + (i = decalsystem->freedecal++);
10742         for (i = decalsystem->freedecal;i < decalsystem->numdecals && decals[i].color4f[0][3];i++)
10743                 ;
10744         decalsystem->freedecal = i;
10745         if (decalsystem->numdecals <= i)
10746                 decalsystem->numdecals = i + 1;
10747
10748         // initialize the decal
10749         decal->lived = 0;
10750         decal->triangleindex = triangleindex;
10751         decal->surfaceindex = surfaceindex;
10752         decal->decalsequence = decalsequence;
10753         decal->color4f[0][0] = c0[0];
10754         decal->color4f[0][1] = c0[1];
10755         decal->color4f[0][2] = c0[2];
10756         decal->color4f[0][3] = 1;
10757         decal->color4f[1][0] = c1[0];
10758         decal->color4f[1][1] = c1[1];
10759         decal->color4f[1][2] = c1[2];
10760         decal->color4f[1][3] = 1;
10761         decal->color4f[2][0] = c2[0];
10762         decal->color4f[2][1] = c2[1];
10763         decal->color4f[2][2] = c2[2];
10764         decal->color4f[2][3] = 1;
10765         decal->vertex3f[0][0] = v0[0];
10766         decal->vertex3f[0][1] = v0[1];
10767         decal->vertex3f[0][2] = v0[2];
10768         decal->vertex3f[1][0] = v1[0];
10769         decal->vertex3f[1][1] = v1[1];
10770         decal->vertex3f[1][2] = v1[2];
10771         decal->vertex3f[2][0] = v2[0];
10772         decal->vertex3f[2][1] = v2[1];
10773         decal->vertex3f[2][2] = v2[2];
10774         decal->texcoord2f[0][0] = t0[0];
10775         decal->texcoord2f[0][1] = t0[1];
10776         decal->texcoord2f[1][0] = t1[0];
10777         decal->texcoord2f[1][1] = t1[1];
10778         decal->texcoord2f[2][0] = t2[0];
10779         decal->texcoord2f[2][1] = t2[1];
10780         TriangleNormal(v0, v1, v2, decal->plane);
10781         VectorNormalize(decal->plane);
10782         decal->plane[3] = DotProduct(v0, decal->plane);
10783 }
10784
10785 extern cvar_t cl_decals_bias;
10786 extern cvar_t cl_decals_models;
10787 extern cvar_t cl_decals_newsystem_intensitymultiplier;
10788 // baseparms, parms, temps
10789 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)
10790 {
10791         int cornerindex;
10792         int index;
10793         float v[9][3];
10794         const float *vertex3f;
10795         const float *normal3f;
10796         int numpoints;
10797         float points[2][9][3];
10798         float temp[3];
10799         float tc[9][2];
10800         float f;
10801         float c[9][4];
10802         const int *e;
10803
10804         e = rsurface.modelelement3i + 3*triangleindex;
10805
10806         vertex3f = rsurface.modelvertex3f;
10807         normal3f = rsurface.modelnormal3f;
10808
10809         if (normal3f)
10810         {
10811                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10812                 {
10813                         index = 3*e[cornerindex];
10814                         VectorMA(vertex3f + index, cl_decals_bias.value, normal3f + index, v[cornerindex]);
10815                 }
10816         }
10817         else
10818         {
10819                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10820                 {
10821                         index = 3*e[cornerindex];
10822                         VectorCopy(vertex3f + index, v[cornerindex]);
10823                 }
10824         }
10825
10826         // cull backfaces
10827         //TriangleNormal(v[0], v[1], v[2], normal);
10828         //if (DotProduct(normal, localnormal) < 0.0f)
10829         //      continue;
10830         // clip by each of the box planes formed from the projection matrix
10831         // if anything survives, we emit the decal
10832         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]);
10833         if (numpoints < 3)
10834                 return;
10835         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]);
10836         if (numpoints < 3)
10837                 return;
10838         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]);
10839         if (numpoints < 3)
10840                 return;
10841         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]);
10842         if (numpoints < 3)
10843                 return;
10844         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]);
10845         if (numpoints < 3)
10846                 return;
10847         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]);
10848         if (numpoints < 3)
10849                 return;
10850         // some part of the triangle survived, so we have to accept it...
10851         if (dynamic)
10852         {
10853                 // dynamic always uses the original triangle
10854                 numpoints = 3;
10855                 for (cornerindex = 0;cornerindex < 3;cornerindex++)
10856                 {
10857                         index = 3*e[cornerindex];
10858                         VectorCopy(vertex3f + index, v[cornerindex]);
10859                 }
10860         }
10861         for (cornerindex = 0;cornerindex < numpoints;cornerindex++)
10862         {
10863                 // convert vertex positions to texcoords
10864                 Matrix4x4_Transform(projection, v[cornerindex], temp);
10865                 tc[cornerindex][0] = (temp[1]+1.0f)*0.5f * (s2-s1) + s1;
10866                 tc[cornerindex][1] = (temp[2]+1.0f)*0.5f * (t2-t1) + t1;
10867                 // calculate distance fade from the projection origin
10868                 f = a * (1.0f-fabs(temp[0])) * cl_decals_newsystem_intensitymultiplier.value;
10869                 f = bound(0.0f, f, 1.0f);
10870                 c[cornerindex][0] = r * f;
10871                 c[cornerindex][1] = g * f;
10872                 c[cornerindex][2] = b * f;
10873                 c[cornerindex][3] = 1.0f;
10874                 //VectorMA(v[cornerindex], cl_decals_bias.value, localnormal, v[cornerindex]);
10875         }
10876         if (dynamic)
10877                 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);
10878         else
10879                 for (cornerindex = 0;cornerindex < numpoints-2;cornerindex++)
10880                         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);
10881 }
10882 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)
10883 {
10884         matrix4x4_t projection;
10885         decalsystem_t *decalsystem;
10886         qboolean dynamic;
10887         dp_model_t *model;
10888         const msurface_t *surface;
10889         const msurface_t *surfaces;
10890         const int *surfacelist;
10891         const texture_t *texture;
10892         int numtriangles;
10893         int numsurfacelist;
10894         int surfacelistindex;
10895         int surfaceindex;
10896         int triangleindex;
10897         float localorigin[3];
10898         float localnormal[3];
10899         float localmins[3];
10900         float localmaxs[3];
10901         float localsize;
10902         //float normal[3];
10903         float planes[6][4];
10904         float angles[3];
10905         bih_t *bih;
10906         int bih_triangles_count;
10907         int bih_triangles[256];
10908         int bih_surfaces[256];
10909
10910         decalsystem = &ent->decalsystem;
10911         model = ent->model;
10912         if (!model || !ent->allowdecals || ent->alpha < 1 || (ent->flags & (RENDER_ADDITIVE | RENDER_NODEPTHTEST)))
10913         {
10914                 R_DecalSystem_Reset(&ent->decalsystem);
10915                 return;
10916         }
10917
10918         if (!model->brush.data_leafs && !cl_decals_models.integer)
10919         {
10920                 if (decalsystem->model)
10921                         R_DecalSystem_Reset(decalsystem);
10922                 return;
10923         }
10924
10925         if (decalsystem->model != model)
10926                 R_DecalSystem_Reset(decalsystem);
10927         decalsystem->model = model;
10928
10929         RSurf_ActiveModelEntity(ent, true, false, false);
10930
10931         Matrix4x4_Transform(&rsurface.inversematrix, worldorigin, localorigin);
10932         Matrix4x4_Transform3x3(&rsurface.inversematrix, worldnormal, localnormal);
10933         VectorNormalize(localnormal);
10934         localsize = worldsize*rsurface.inversematrixscale;
10935         localmins[0] = localorigin[0] - localsize;
10936         localmins[1] = localorigin[1] - localsize;
10937         localmins[2] = localorigin[2] - localsize;
10938         localmaxs[0] = localorigin[0] + localsize;
10939         localmaxs[1] = localorigin[1] + localsize;
10940         localmaxs[2] = localorigin[2] + localsize;
10941
10942         //VectorCopy(localnormal, planes[4]);
10943         //VectorVectors(planes[4], planes[2], planes[0]);
10944         AnglesFromVectors(angles, localnormal, NULL, false);
10945         AngleVectors(angles, planes[0], planes[2], planes[4]);
10946         VectorNegate(planes[0], planes[1]);
10947         VectorNegate(planes[2], planes[3]);
10948         VectorNegate(planes[4], planes[5]);
10949         planes[0][3] = DotProduct(planes[0], localorigin) - localsize;
10950         planes[1][3] = DotProduct(planes[1], localorigin) - localsize;
10951         planes[2][3] = DotProduct(planes[2], localorigin) - localsize;
10952         planes[3][3] = DotProduct(planes[3], localorigin) - localsize;
10953         planes[4][3] = DotProduct(planes[4], localorigin) - localsize;
10954         planes[5][3] = DotProduct(planes[5], localorigin) - localsize;
10955
10956 #if 1
10957 // works
10958 {
10959         matrix4x4_t forwardprojection;
10960         Matrix4x4_CreateFromQuakeEntity(&forwardprojection, localorigin[0], localorigin[1], localorigin[2], angles[0], angles[1], angles[2], localsize);
10961         Matrix4x4_Invert_Simple(&projection, &forwardprojection);
10962 }
10963 #else
10964 // broken
10965 {
10966         float projectionvector[4][3];
10967         VectorScale(planes[0], ilocalsize, projectionvector[0]);
10968         VectorScale(planes[2], ilocalsize, projectionvector[1]);
10969         VectorScale(planes[4], ilocalsize, projectionvector[2]);
10970         projectionvector[0][0] = planes[0][0] * ilocalsize;
10971         projectionvector[0][1] = planes[1][0] * ilocalsize;
10972         projectionvector[0][2] = planes[2][0] * ilocalsize;
10973         projectionvector[1][0] = planes[0][1] * ilocalsize;
10974         projectionvector[1][1] = planes[1][1] * ilocalsize;
10975         projectionvector[1][2] = planes[2][1] * ilocalsize;
10976         projectionvector[2][0] = planes[0][2] * ilocalsize;
10977         projectionvector[2][1] = planes[1][2] * ilocalsize;
10978         projectionvector[2][2] = planes[2][2] * ilocalsize;
10979         projectionvector[3][0] = -(localorigin[0]*projectionvector[0][0]+localorigin[1]*projectionvector[1][0]+localorigin[2]*projectionvector[2][0]);
10980         projectionvector[3][1] = -(localorigin[0]*projectionvector[0][1]+localorigin[1]*projectionvector[1][1]+localorigin[2]*projectionvector[2][1]);
10981         projectionvector[3][2] = -(localorigin[0]*projectionvector[0][2]+localorigin[1]*projectionvector[1][2]+localorigin[2]*projectionvector[2][2]);
10982         Matrix4x4_FromVectors(&projection, projectionvector[0], projectionvector[1], projectionvector[2], projectionvector[3]);
10983 }
10984 #endif
10985
10986         dynamic = model->surfmesh.isanimated;
10987         numsurfacelist = model->nummodelsurfaces;
10988         surfacelist = model->sortedmodelsurfaces;
10989         surfaces = model->data_surfaces;
10990
10991         bih = NULL;
10992         bih_triangles_count = -1;
10993         if(!dynamic)
10994         {
10995                 if(model->render_bih.numleafs)
10996                         bih = &model->render_bih;
10997                 else if(model->collision_bih.numleafs)
10998                         bih = &model->collision_bih;
10999         }
11000         if(bih)
11001                 bih_triangles_count = BIH_GetTriangleListForBox(bih, sizeof(bih_triangles) / sizeof(*bih_triangles), bih_triangles, bih_surfaces, localmins, localmaxs);
11002         if(bih_triangles_count == 0)
11003                 return;
11004         if(bih_triangles_count > (int) (sizeof(bih_triangles) / sizeof(*bih_triangles))) // hit too many, likely bad anyway
11005                 return;
11006         if(bih_triangles_count > 0)
11007         {
11008                 for (triangleindex = 0; triangleindex < bih_triangles_count; ++triangleindex)
11009                 {
11010                         surfaceindex = bih_surfaces[triangleindex];
11011                         surface = surfaces + surfaceindex;
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                         R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, bih_triangles[triangleindex], surfaceindex);
11018                 }
11019         }
11020         else
11021         {
11022                 for (surfacelistindex = 0;surfacelistindex < numsurfacelist;surfacelistindex++)
11023                 {
11024                         surfaceindex = surfacelist[surfacelistindex];
11025                         surface = surfaces + surfaceindex;
11026                         // check cull box first because it rejects more than any other check
11027                         if (!dynamic && !BoxesOverlap(surface->mins, surface->maxs, localmins, localmaxs))
11028                                 continue;
11029                         // skip transparent surfaces
11030                         texture = surface->texture;
11031                         if (texture->currentmaterialflags & (MATERIALFLAG_BLENDED | MATERIALFLAG_NODEPTHTEST | MATERIALFLAG_SKY | MATERIALFLAG_SHORTDEPTHRANGE | MATERIALFLAG_WATERSHADER | MATERIALFLAG_REFRACTION))
11032                                 continue;
11033                         if (texture->surfaceflags & Q3SURFACEFLAG_NOMARKS)
11034                                 continue;
11035                         numtriangles = surface->num_triangles;
11036                         for (triangleindex = 0; triangleindex < numtriangles; triangleindex++)
11037                                 R_DecalSystem_SplatTriangle(decalsystem, r, g, b, a, s1, t1, s2, t2, decalsequence, dynamic, planes, &projection, triangleindex + surface->num_firsttriangle, surfaceindex);
11038                 }
11039         }
11040 }
11041
11042 // do not call this outside of rendering code - use R_DecalSystem_SplatEntities instead
11043 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)
11044 {
11045         int renderentityindex;
11046         float worldmins[3];
11047         float worldmaxs[3];
11048         entity_render_t *ent;
11049
11050         if (!cl_decals_newsystem.integer)
11051                 return;
11052
11053         worldmins[0] = worldorigin[0] - worldsize;
11054         worldmins[1] = worldorigin[1] - worldsize;
11055         worldmins[2] = worldorigin[2] - worldsize;
11056         worldmaxs[0] = worldorigin[0] + worldsize;
11057         worldmaxs[1] = worldorigin[1] + worldsize;
11058         worldmaxs[2] = worldorigin[2] + worldsize;
11059
11060         R_DecalSystem_SplatEntity(r_refdef.scene.worldentity, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11061
11062         for (renderentityindex = 0;renderentityindex < r_refdef.scene.numentities;renderentityindex++)
11063         {
11064                 ent = r_refdef.scene.entities[renderentityindex];
11065                 if (!BoxesOverlap(ent->mins, ent->maxs, worldmins, worldmaxs))
11066                         continue;
11067
11068                 R_DecalSystem_SplatEntity(ent, worldorigin, worldnormal, r, g, b, a, s1, t1, s2, t2, worldsize, decalsequence);
11069         }
11070 }
11071
11072 typedef struct r_decalsystem_splatqueue_s
11073 {
11074         vec3_t worldorigin;
11075         vec3_t worldnormal;
11076         float color[4];
11077         float tcrange[4];
11078         float worldsize;
11079         int decalsequence;
11080 }
11081 r_decalsystem_splatqueue_t;
11082
11083 int r_decalsystem_numqueued = 0;
11084 r_decalsystem_splatqueue_t r_decalsystem_queue[MAX_DECALSYSTEM_QUEUE];
11085
11086 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)
11087 {
11088         r_decalsystem_splatqueue_t *queue;
11089
11090         if (!cl_decals_newsystem.integer || r_decalsystem_numqueued == MAX_DECALSYSTEM_QUEUE)
11091                 return;
11092
11093         queue = &r_decalsystem_queue[r_decalsystem_numqueued++];
11094         VectorCopy(worldorigin, queue->worldorigin);
11095         VectorCopy(worldnormal, queue->worldnormal);
11096         Vector4Set(queue->color, r, g, b, a);
11097         Vector4Set(queue->tcrange, s1, t1, s2, t2);
11098         queue->worldsize = worldsize;
11099         queue->decalsequence = cl.decalsequence++;
11100 }
11101
11102 static void R_DecalSystem_ApplySplatEntitiesQueue(void)
11103 {
11104         int i;
11105         r_decalsystem_splatqueue_t *queue;
11106
11107         for (i = 0, queue = r_decalsystem_queue;i < r_decalsystem_numqueued;i++, queue++)
11108                 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);
11109         r_decalsystem_numqueued = 0;
11110 }
11111
11112 extern cvar_t cl_decals_max;
11113 static void R_DrawModelDecals_FadeEntity(entity_render_t *ent)
11114 {
11115         int i;
11116         decalsystem_t *decalsystem = &ent->decalsystem;
11117         int numdecals;
11118         int killsequence;
11119         tridecal_t *decal;
11120         float frametime;
11121         float lifetime;
11122
11123         if (!decalsystem->numdecals)
11124                 return;
11125
11126         if (r_showsurfaces.integer)
11127                 return;
11128
11129         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11130         {
11131                 R_DecalSystem_Reset(decalsystem);
11132                 return;
11133         }
11134
11135         killsequence = cl.decalsequence - max(1, cl_decals_max.integer);
11136         lifetime = cl_decals_time.value + cl_decals_fadetime.value;
11137
11138         if (decalsystem->lastupdatetime)
11139                 frametime = (r_refdef.scene.time - decalsystem->lastupdatetime);
11140         else
11141                 frametime = 0;
11142         decalsystem->lastupdatetime = r_refdef.scene.time;
11143         decal = decalsystem->decals;
11144         numdecals = decalsystem->numdecals;
11145
11146         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11147         {
11148                 if (decal->color4f[0][3])
11149                 {
11150                         decal->lived += frametime;
11151                         if (killsequence - decal->decalsequence > 0 || decal->lived >= lifetime)
11152                         {
11153                                 memset(decal, 0, sizeof(*decal));
11154                                 if (decalsystem->freedecal > i)
11155                                         decalsystem->freedecal = i;
11156                         }
11157                 }
11158         }
11159         decal = decalsystem->decals;
11160         while (numdecals > 0 && !decal[numdecals-1].color4f[0][3])
11161                 numdecals--;
11162
11163         // collapse the array by shuffling the tail decals into the gaps
11164         for (;;)
11165         {
11166                 while (decalsystem->freedecal < numdecals && decal[decalsystem->freedecal].color4f[0][3])
11167                         decalsystem->freedecal++;
11168                 if (decalsystem->freedecal == numdecals)
11169                         break;
11170                 decal[decalsystem->freedecal] = decal[--numdecals];
11171         }
11172
11173         decalsystem->numdecals = numdecals;
11174
11175         if (numdecals <= 0)
11176         {
11177                 // if there are no decals left, reset decalsystem
11178                 R_DecalSystem_Reset(decalsystem);
11179         }
11180 }
11181
11182 extern skinframe_t *decalskinframe;
11183 static void R_DrawModelDecals_Entity(entity_render_t *ent)
11184 {
11185         int i;
11186         decalsystem_t *decalsystem = &ent->decalsystem;
11187         int numdecals;
11188         tridecal_t *decal;
11189         float faderate;
11190         float alpha;
11191         float *v3f;
11192         float *c4f;
11193         float *t2f;
11194         const int *e;
11195         const unsigned char *surfacevisible = ent == r_refdef.scene.worldentity ? r_refdef.viewcache.world_surfacevisible : NULL;
11196         int numtris = 0;
11197
11198         numdecals = decalsystem->numdecals;
11199         if (!numdecals)
11200                 return;
11201
11202         if (r_showsurfaces.integer)
11203                 return;
11204
11205         if (ent->model != decalsystem->model || ent->alpha < 1 || (ent->flags & RENDER_ADDITIVE))
11206         {
11207                 R_DecalSystem_Reset(decalsystem);
11208                 return;
11209         }
11210
11211         // if the model is static it doesn't matter what value we give for
11212         // wantnormals and wanttangents, so this logic uses only rules applicable
11213         // to a model, knowing that they are meaningless otherwise
11214         if (ent == r_refdef.scene.worldentity)
11215                 RSurf_ActiveWorldEntity();
11216         else
11217                 RSurf_ActiveModelEntity(ent, false, false, false);
11218
11219         decalsystem->lastupdatetime = r_refdef.scene.time;
11220         decal = decalsystem->decals;
11221
11222         faderate = 1.0f / max(0.001f, cl_decals_fadetime.value);
11223
11224         // update vertex positions for animated models
11225         v3f = decalsystem->vertex3f;
11226         c4f = decalsystem->color4f;
11227         t2f = decalsystem->texcoord2f;
11228         for (i = 0, decal = decalsystem->decals;i < numdecals;i++, decal++)
11229         {
11230                 if (!decal->color4f[0][3])
11231                         continue;
11232
11233                 if (surfacevisible && !surfacevisible[decal->surfaceindex])
11234                         continue;
11235
11236                 // skip backfaces
11237                 if (decal->triangleindex < 0 && DotProduct(r_refdef.view.origin, decal->plane) < decal->plane[3])
11238                         continue;
11239
11240                 // update color values for fading decals
11241                 if (decal->lived >= cl_decals_time.value)
11242                         alpha = 1 - faderate * (decal->lived - cl_decals_time.value);
11243                 else
11244                         alpha = 1.0f;
11245
11246                 c4f[ 0] = decal->color4f[0][0] * alpha;
11247                 c4f[ 1] = decal->color4f[0][1] * alpha;
11248                 c4f[ 2] = decal->color4f[0][2] * alpha;
11249                 c4f[ 3] = 1;
11250                 c4f[ 4] = decal->color4f[1][0] * alpha;
11251                 c4f[ 5] = decal->color4f[1][1] * alpha;
11252                 c4f[ 6] = decal->color4f[1][2] * alpha;
11253                 c4f[ 7] = 1;
11254                 c4f[ 8] = decal->color4f[2][0] * alpha;
11255                 c4f[ 9] = decal->color4f[2][1] * alpha;
11256                 c4f[10] = decal->color4f[2][2] * alpha;
11257                 c4f[11] = 1;
11258
11259                 t2f[0] = decal->texcoord2f[0][0];
11260                 t2f[1] = decal->texcoord2f[0][1];
11261                 t2f[2] = decal->texcoord2f[1][0];
11262                 t2f[3] = decal->texcoord2f[1][1];
11263                 t2f[4] = decal->texcoord2f[2][0];
11264                 t2f[5] = decal->texcoord2f[2][1];
11265
11266                 // update vertex positions for animated models
11267                 if (decal->triangleindex >= 0 && decal->triangleindex < rsurface.modelnumtriangles)
11268                 {
11269                         e = rsurface.modelelement3i + 3*decal->triangleindex;
11270                         VectorCopy(rsurface.modelvertex3f + 3*e[0], v3f);
11271                         VectorCopy(rsurface.modelvertex3f + 3*e[1], v3f + 3);
11272                         VectorCopy(rsurface.modelvertex3f + 3*e[2], v3f + 6);
11273                 }
11274                 else
11275                 {
11276                         VectorCopy(decal->vertex3f[0], v3f);
11277                         VectorCopy(decal->vertex3f[1], v3f + 3);
11278                         VectorCopy(decal->vertex3f[2], v3f + 6);
11279                 }
11280
11281                 if (r_refdef.fogenabled)
11282                 {
11283                         alpha = RSurf_FogVertex(v3f);
11284                         VectorScale(c4f, alpha, c4f);
11285                         alpha = RSurf_FogVertex(v3f + 3);
11286                         VectorScale(c4f + 4, alpha, c4f + 4);
11287                         alpha = RSurf_FogVertex(v3f + 6);
11288                         VectorScale(c4f + 8, alpha, c4f + 8);
11289                 }
11290
11291                 v3f += 9;
11292                 c4f += 12;
11293                 t2f += 6;
11294                 numtris++;
11295         }
11296
11297         if (numtris > 0)
11298         {
11299                 r_refdef.stats.drawndecals += numtris;
11300
11301                 // now render the decals all at once
11302                 // (this assumes they all use one particle font texture!)
11303                 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);
11304 //              R_Mesh_ResetTextureState();
11305                 R_Mesh_PrepareVertices_Generic_Arrays(numtris * 3, decalsystem->vertex3f, decalsystem->color4f, decalsystem->texcoord2f);
11306                 GL_DepthMask(false);
11307                 GL_DepthRange(0, 1);
11308                 GL_PolygonOffset(rsurface.basepolygonfactor + r_polygonoffset_decals_factor.value, rsurface.basepolygonoffset + r_polygonoffset_decals_offset.value);
11309                 GL_DepthTest(true);
11310                 GL_CullFace(GL_NONE);
11311                 GL_BlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
11312                 R_SetupShader_Generic(decalskinframe->base, NULL, GL_MODULATE, 1, false, false, false);
11313                 R_Mesh_Draw(0, numtris * 3, 0, numtris, decalsystem->element3i, NULL, 0, decalsystem->element3s, NULL, 0);
11314         }
11315 }
11316
11317 static void R_DrawModelDecals(void)
11318 {
11319         int i, numdecals;
11320
11321         // fade faster when there are too many decals
11322         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11323         for (i = 0;i < r_refdef.scene.numentities;i++)
11324                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11325
11326         R_DrawModelDecals_FadeEntity(r_refdef.scene.worldentity);
11327         for (i = 0;i < r_refdef.scene.numentities;i++)
11328                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11329                         R_DrawModelDecals_FadeEntity(r_refdef.scene.entities[i]);
11330
11331         R_DecalSystem_ApplySplatEntitiesQueue();
11332
11333         numdecals = r_refdef.scene.worldentity->decalsystem.numdecals;
11334         for (i = 0;i < r_refdef.scene.numentities;i++)
11335                 numdecals += r_refdef.scene.entities[i]->decalsystem.numdecals;
11336
11337         r_refdef.stats.totaldecals += numdecals;
11338
11339         if (r_showsurfaces.integer)
11340                 return;
11341
11342         R_DrawModelDecals_Entity(r_refdef.scene.worldentity);
11343
11344         for (i = 0;i < r_refdef.scene.numentities;i++)
11345         {
11346                 if (!r_refdef.viewcache.entityvisible[i])
11347                         continue;
11348                 if (r_refdef.scene.entities[i]->decalsystem.numdecals)
11349                         R_DrawModelDecals_Entity(r_refdef.scene.entities[i]);
11350         }
11351 }
11352
11353 extern cvar_t mod_collision_bih;
11354 static void R_DrawDebugModel(void)
11355 {
11356         entity_render_t *ent = rsurface.entity;
11357         int i, j, k, l, flagsmask;
11358         const msurface_t *surface;
11359         dp_model_t *model = ent->model;
11360         vec3_t v;
11361
11362         if (!sv.active  && !cls.demoplayback && ent != r_refdef.scene.worldentity)
11363                 return;
11364
11365         if (r_showoverdraw.value > 0)
11366         {
11367                 float c = r_refdef.view.colorscale * r_showoverdraw.value * 0.125f;
11368                 flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11369                 R_SetupShader_Generic_NoTexture(false, false);
11370                 GL_DepthTest(false);
11371                 GL_DepthMask(false);
11372                 GL_DepthRange(0, 1);
11373                 GL_BlendFunc(GL_ONE, GL_ONE);
11374                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11375                 {
11376                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11377                                 continue;
11378                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11379                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11380                         {
11381                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_NOGAPS, 1, &surface);
11382                                 GL_CullFace((rsurface.texture->currentmaterialflags & MATERIALFLAG_NOCULLFACE) ? GL_NONE : r_refdef.view.cullface_back);
11383                                 if (!rsurface.texture->currentlayers->depthmask)
11384                                         GL_Color(c, 0, 0, 1.0f);
11385                                 else if (ent == r_refdef.scene.worldentity)
11386                                         GL_Color(c, c, c, 1.0f);
11387                                 else
11388                                         GL_Color(0, c, 0, 1.0f);
11389                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11390                                 RSurf_DrawBatch();
11391                         }
11392                 }
11393                 rsurface.texture = NULL;
11394         }
11395
11396         flagsmask = MATERIALFLAG_SKY | MATERIALFLAG_WALL;
11397
11398 //      R_Mesh_ResetTextureState();
11399         R_SetupShader_Generic_NoTexture(false, false);
11400         GL_DepthRange(0, 1);
11401         GL_DepthTest(!r_showdisabledepthtest.integer);
11402         GL_DepthMask(false);
11403         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11404
11405         if (r_showcollisionbrushes.value > 0 && model->collision_bih.numleafs)
11406         {
11407                 int triangleindex;
11408                 int bihleafindex;
11409                 qboolean cullbox = ent == r_refdef.scene.worldentity;
11410                 const q3mbrush_t *brush;
11411                 const bih_t *bih = &model->collision_bih;
11412                 const bih_leaf_t *bihleaf;
11413                 float vertex3f[3][3];
11414                 GL_PolygonOffset(r_refdef.polygonfactor + r_showcollisionbrushes_polygonfactor.value, r_refdef.polygonoffset + r_showcollisionbrushes_polygonoffset.value);
11415                 cullbox = false;
11416                 for (bihleafindex = 0, bihleaf = bih->leafs;bihleafindex < bih->numleafs;bihleafindex++, bihleaf++)
11417                 {
11418                         if (cullbox && R_CullBox(bihleaf->mins, bihleaf->maxs))
11419                                 continue;
11420                         switch (bihleaf->type)
11421                         {
11422                         case BIH_BRUSH:
11423                                 brush = model->brush.data_brushes + bihleaf->itemindex;
11424                                 if (brush->colbrushf && brush->colbrushf->numtriangles)
11425                                 {
11426                                         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);
11427                                         R_Mesh_PrepareVertices_Generic_Arrays(brush->colbrushf->numpoints, brush->colbrushf->points->v, NULL, NULL);
11428                                         R_Mesh_Draw(0, brush->colbrushf->numpoints, 0, brush->colbrushf->numtriangles, brush->colbrushf->elements, NULL, 0, NULL, NULL, 0);
11429                                 }
11430                                 break;
11431                         case BIH_COLLISIONTRIANGLE:
11432                                 triangleindex = bihleaf->itemindex;
11433                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+0], vertex3f[0]);
11434                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+1], vertex3f[1]);
11435                                 VectorCopy(model->brush.data_collisionvertex3f + 3*model->brush.data_collisionelement3i[triangleindex*3+2], vertex3f[2]);
11436                                 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);
11437                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11438                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11439                                 break;
11440                         case BIH_RENDERTRIANGLE:
11441                                 triangleindex = bihleaf->itemindex;
11442                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+0], vertex3f[0]);
11443                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+1], vertex3f[1]);
11444                                 VectorCopy(model->surfmesh.data_vertex3f + 3*model->surfmesh.data_element3i[triangleindex*3+2], vertex3f[2]);
11445                                 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);
11446                                 R_Mesh_PrepareVertices_Generic_Arrays(3, vertex3f[0], NULL, NULL);
11447                                 R_Mesh_Draw(0, 3, 0, 1, polygonelement3i, NULL, 0, polygonelement3s, NULL, 0);
11448                                 break;
11449                         }
11450                 }
11451         }
11452
11453         GL_PolygonOffset(r_refdef.polygonfactor, r_refdef.polygonoffset);
11454
11455 #ifndef USE_GLES2
11456         if (r_showtris.integer && qglPolygonMode)
11457         {
11458                 if (r_showdisabledepthtest.integer)
11459                 {
11460                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11461                         GL_DepthMask(false);
11462                 }
11463                 else
11464                 {
11465                         GL_BlendFunc(GL_ONE, GL_ZERO);
11466                         GL_DepthMask(true);
11467                 }
11468                 qglPolygonMode(GL_FRONT_AND_BACK, GL_LINE);CHECKGLERROR
11469                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11470                 {
11471                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11472                                 continue;
11473                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11474                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11475                         {
11476                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11477                                 if (!rsurface.texture->currentlayers->depthmask)
11478                                         GL_Color(r_refdef.view.colorscale, 0, 0, r_showtris.value);
11479                                 else if (ent == r_refdef.scene.worldentity)
11480                                         GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, r_showtris.value);
11481                                 else
11482                                         GL_Color(0, r_refdef.view.colorscale, 0, r_showtris.value);
11483                                 R_Mesh_PrepareVertices_Generic_Arrays(rsurface.batchnumvertices, rsurface.batchvertex3f, NULL, NULL);
11484                                 RSurf_DrawBatch();
11485                         }
11486                 }
11487                 qglPolygonMode(GL_FRONT_AND_BACK, GL_FILL);CHECKGLERROR
11488                 rsurface.texture = NULL;
11489         }
11490
11491         if (r_shownormals.value != 0 && qglBegin)
11492         {
11493                 if (r_showdisabledepthtest.integer)
11494                 {
11495                         GL_BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
11496                         GL_DepthMask(false);
11497                 }
11498                 else
11499                 {
11500                         GL_BlendFunc(GL_ONE, GL_ZERO);
11501                         GL_DepthMask(true);
11502                 }
11503                 for (i = 0, j = model->firstmodelsurface, surface = model->data_surfaces + j;i < model->nummodelsurfaces;i++, j++, surface++)
11504                 {
11505                         if (ent == r_refdef.scene.worldentity && !r_refdef.viewcache.world_surfacevisible[j])
11506                                 continue;
11507                         rsurface.texture = R_GetCurrentTexture(surface->texture);
11508                         if ((rsurface.texture->currentmaterialflags & flagsmask) && surface->num_triangles)
11509                         {
11510                                 RSurf_PrepareVerticesForBatch(BATCHNEED_ARRAY_VERTEX | BATCHNEED_ARRAY_NORMAL | BATCHNEED_ARRAY_VECTOR | BATCHNEED_NOGAPS, 1, &surface);
11511                                 qglBegin(GL_LINES);
11512                                 if (r_shownormals.value < 0 && rsurface.batchnormal3f)
11513                                 {
11514                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11515                                         {
11516                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11517                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11518                                                 qglVertex3f(v[0], v[1], v[2]);
11519                                                 VectorMA(v, -r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11520                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11521                                                 qglVertex3f(v[0], v[1], v[2]);
11522                                         }
11523                                 }
11524                                 if (r_shownormals.value > 0 && rsurface.batchsvector3f)
11525                                 {
11526                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11527                                         {
11528                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11529                                                 GL_Color(r_refdef.view.colorscale, 0, 0, 1);
11530                                                 qglVertex3f(v[0], v[1], v[2]);
11531                                                 VectorMA(v, r_shownormals.value, rsurface.batchsvector3f + l * 3, v);
11532                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11533                                                 qglVertex3f(v[0], v[1], v[2]);
11534                                         }
11535                                 }
11536                                 if (r_shownormals.value > 0 && rsurface.batchtvector3f)
11537                                 {
11538                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11539                                         {
11540                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11541                                                 GL_Color(0, r_refdef.view.colorscale, 0, 1);
11542                                                 qglVertex3f(v[0], v[1], v[2]);
11543                                                 VectorMA(v, r_shownormals.value, rsurface.batchtvector3f + l * 3, v);
11544                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11545                                                 qglVertex3f(v[0], v[1], v[2]);
11546                                         }
11547                                 }
11548                                 if (r_shownormals.value > 0 && rsurface.batchnormal3f)
11549                                 {
11550                                         for (k = 0, l = rsurface.batchfirstvertex;k < rsurface.batchnumvertices;k++, l++)
11551                                         {
11552                                                 VectorCopy(rsurface.batchvertex3f + l * 3, v);
11553                                                 GL_Color(0, 0, r_refdef.view.colorscale, 1);
11554                                                 qglVertex3f(v[0], v[1], v[2]);
11555                                                 VectorMA(v, r_shownormals.value, rsurface.batchnormal3f + l * 3, v);
11556                                                 GL_Color(r_refdef.view.colorscale, r_refdef.view.colorscale, r_refdef.view.colorscale, 1);
11557                                                 qglVertex3f(v[0], v[1], v[2]);
11558                                         }
11559                                 }
11560                                 qglEnd();
11561                                 CHECKGLERROR
11562                         }
11563                 }
11564                 rsurface.texture = NULL;
11565         }
11566 #endif
11567 }
11568
11569 int r_maxsurfacelist = 0;
11570 const msurface_t **r_surfacelist = NULL;
11571 void R_DrawWorldSurfaces(qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11572 {
11573         int i, j, endj, flagsmask;
11574         dp_model_t *model = r_refdef.scene.worldmodel;
11575         msurface_t *surfaces;
11576         unsigned char *update;
11577         int numsurfacelist = 0;
11578         if (model == NULL)
11579                 return;
11580
11581         if (r_maxsurfacelist < model->num_surfaces)
11582         {
11583                 r_maxsurfacelist = model->num_surfaces;
11584                 if (r_surfacelist)
11585                         Mem_Free((msurface_t**)r_surfacelist);
11586                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11587         }
11588
11589         RSurf_ActiveWorldEntity();
11590
11591         surfaces = model->data_surfaces;
11592         update = model->brushq1.lightmapupdateflags;
11593
11594         // update light styles on this submodel
11595         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11596         {
11597                 model_brush_lightstyleinfo_t *style;
11598                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11599                 {
11600                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11601                         {
11602                                 int *list = style->surfacelist;
11603                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11604                                 for (j = 0;j < style->numsurfaces;j++)
11605                                         update[list[j]] = true;
11606                         }
11607                 }
11608         }
11609
11610         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11611
11612         if (debug)
11613         {
11614                 R_DrawDebugModel();
11615                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11616                 return;
11617         }
11618
11619         rsurface.lightmaptexture = NULL;
11620         rsurface.deluxemaptexture = NULL;
11621         rsurface.uselightmaptexture = false;
11622         rsurface.texture = NULL;
11623         rsurface.rtlight = NULL;
11624         numsurfacelist = 0;
11625         // add visible surfaces to draw list
11626         for (i = 0;i < model->nummodelsurfaces;i++)
11627         {
11628                 j = model->sortedmodelsurfaces[i];
11629                 if (r_refdef.viewcache.world_surfacevisible[j])
11630                         r_surfacelist[numsurfacelist++] = surfaces + j;
11631         }
11632         // update lightmaps if needed
11633         if (model->brushq1.firstrender)
11634         {
11635                 model->brushq1.firstrender = false;
11636                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11637                         if (update[j])
11638                                 R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11639         }
11640         else if (update)
11641         {
11642                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11643                         if (r_refdef.viewcache.world_surfacevisible[j])
11644                                 if (update[j])
11645                                         R_BuildLightMap(r_refdef.scene.worldentity, surfaces + j);
11646         }
11647         // don't do anything if there were no surfaces
11648         if (!numsurfacelist)
11649         {
11650                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11651                 return;
11652         }
11653         R_QueueWorldSurfaceList(numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11654
11655         // add to stats if desired
11656         if (r_speeds.integer && !skysurfaces && !depthonly)
11657         {
11658                 r_refdef.stats.world_surfaces += numsurfacelist;
11659                 for (j = 0;j < numsurfacelist;j++)
11660                         r_refdef.stats.world_triangles += r_surfacelist[j]->num_triangles;
11661         }
11662
11663         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11664 }
11665
11666 void R_DrawModelSurfaces(entity_render_t *ent, qboolean skysurfaces, qboolean writedepth, qboolean depthonly, qboolean debug, qboolean prepass)
11667 {
11668         int i, j, endj, flagsmask;
11669         dp_model_t *model = ent->model;
11670         msurface_t *surfaces;
11671         unsigned char *update;
11672         int numsurfacelist = 0;
11673         if (model == NULL)
11674                 return;
11675
11676         if (r_maxsurfacelist < model->num_surfaces)
11677         {
11678                 r_maxsurfacelist = model->num_surfaces;
11679                 if (r_surfacelist)
11680                         Mem_Free((msurface_t **)r_surfacelist);
11681                 r_surfacelist = (const msurface_t **) Mem_Alloc(r_main_mempool, r_maxsurfacelist * sizeof(*r_surfacelist));
11682         }
11683
11684         // if the model is static it doesn't matter what value we give for
11685         // wantnormals and wanttangents, so this logic uses only rules applicable
11686         // to a model, knowing that they are meaningless otherwise
11687         if (ent == r_refdef.scene.worldentity)
11688                 RSurf_ActiveWorldEntity();
11689         else if (r_showsurfaces.integer && r_showsurfaces.integer != 3)
11690                 RSurf_ActiveModelEntity(ent, false, false, false);
11691         else if (prepass)
11692                 RSurf_ActiveModelEntity(ent, true, true, true);
11693         else if (depthonly)
11694         {
11695                 switch (vid.renderpath)
11696                 {
11697                 case RENDERPATH_GL20:
11698                 case RENDERPATH_D3D9:
11699                 case RENDERPATH_D3D10:
11700                 case RENDERPATH_D3D11:
11701                 case RENDERPATH_SOFT:
11702                 case RENDERPATH_GLES2:
11703                         RSurf_ActiveModelEntity(ent, model->wantnormals, model->wanttangents, false);
11704                         break;
11705                 case RENDERPATH_GL11:
11706                 case RENDERPATH_GL13:
11707                 case RENDERPATH_GLES1:
11708                         RSurf_ActiveModelEntity(ent, model->wantnormals, false, false);
11709                         break;
11710                 }
11711         }
11712         else
11713         {
11714                 switch (vid.renderpath)
11715                 {
11716                 case RENDERPATH_GL20:
11717                 case RENDERPATH_D3D9:
11718                 case RENDERPATH_D3D10:
11719                 case RENDERPATH_D3D11:
11720                 case RENDERPATH_SOFT:
11721                 case RENDERPATH_GLES2:
11722                         RSurf_ActiveModelEntity(ent, true, true, false);
11723                         break;
11724                 case RENDERPATH_GL11:
11725                 case RENDERPATH_GL13:
11726                 case RENDERPATH_GLES1:
11727                         RSurf_ActiveModelEntity(ent, true, false, false);
11728                         break;
11729                 }
11730         }
11731
11732         surfaces = model->data_surfaces;
11733         update = model->brushq1.lightmapupdateflags;
11734
11735         // update light styles
11736         if (!skysurfaces && !depthonly && !prepass && model->brushq1.num_lightstyles && r_refdef.lightmapintensity > 0)
11737         {
11738                 model_brush_lightstyleinfo_t *style;
11739                 for (i = 0, style = model->brushq1.data_lightstyleinfo;i < model->brushq1.num_lightstyles;i++, style++)
11740                 {
11741                         if (style->value != r_refdef.scene.lightstylevalue[style->style])
11742                         {
11743                                 int *list = style->surfacelist;
11744                                 style->value = r_refdef.scene.lightstylevalue[style->style];
11745                                 for (j = 0;j < style->numsurfaces;j++)
11746                                         update[list[j]] = true;
11747                         }
11748                 }
11749         }
11750
11751         flagsmask = skysurfaces ? MATERIALFLAG_SKY : MATERIALFLAG_WALL;
11752
11753         if (debug)
11754         {
11755                 R_DrawDebugModel();
11756                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11757                 return;
11758         }
11759
11760         rsurface.lightmaptexture = NULL;
11761         rsurface.deluxemaptexture = NULL;
11762         rsurface.uselightmaptexture = false;
11763         rsurface.texture = NULL;
11764         rsurface.rtlight = NULL;
11765         numsurfacelist = 0;
11766         // add visible surfaces to draw list
11767         for (i = 0;i < model->nummodelsurfaces;i++)
11768                 r_surfacelist[numsurfacelist++] = surfaces + model->sortedmodelsurfaces[i];
11769         // don't do anything if there were no surfaces
11770         if (!numsurfacelist)
11771         {
11772                 rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11773                 return;
11774         }
11775         // update lightmaps if needed
11776         if (update)
11777         {
11778                 int updated = 0;
11779                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11780                 {
11781                         if (update[j])
11782                         {
11783                                 updated++;
11784                                 R_BuildLightMap(ent, surfaces + j);
11785                         }
11786                 }
11787         }
11788         if (update)
11789                 for (j = model->firstmodelsurface, endj = model->firstmodelsurface + model->nummodelsurfaces;j < endj;j++)
11790                         if (update[j])
11791                                 R_BuildLightMap(ent, surfaces + j);
11792         R_QueueModelSurfaceList(ent, numsurfacelist, r_surfacelist, flagsmask, writedepth, depthonly, prepass);
11793
11794         // add to stats if desired
11795         if (r_speeds.integer && !skysurfaces && !depthonly)
11796         {
11797                 r_refdef.stats.entities_surfaces += numsurfacelist;
11798                 for (j = 0;j < numsurfacelist;j++)
11799                         r_refdef.stats.entities_triangles += r_surfacelist[j]->num_triangles;
11800         }
11801
11802         rsurface.entity = NULL; // used only by R_GetCurrentTexture and RSurf_ActiveWorldEntity/RSurf_ActiveModelEntity
11803 }
11804
11805 void R_DrawCustomSurface(skinframe_t *skinframe, const matrix4x4_t *texmatrix, int materialflags, int firstvertex, int numvertices, int firsttriangle, int numtriangles, qboolean writedepth, qboolean prepass)
11806 {
11807         static texture_t texture;
11808         static msurface_t surface;
11809         const msurface_t *surfacelist = &surface;
11810
11811         // fake enough texture and surface state to render this geometry
11812
11813         texture.update_lastrenderframe = -1; // regenerate this texture
11814         texture.basematerialflags = materialflags | MATERIALFLAG_CUSTOMSURFACE | MATERIALFLAG_WALL;
11815         texture.currentskinframe = skinframe;
11816         texture.currenttexmatrix = *texmatrix; // requires MATERIALFLAG_CUSTOMSURFACE
11817         texture.offsetmapping = OFFSETMAPPING_OFF;
11818         texture.offsetscale = 1;
11819         texture.specularscalemod = 1;
11820         texture.specularpowermod = 1;
11821
11822         surface.texture = &texture;
11823         surface.num_triangles = numtriangles;
11824         surface.num_firsttriangle = firsttriangle;
11825         surface.num_vertices = numvertices;
11826         surface.num_firstvertex = firstvertex;
11827
11828         // now render it
11829         rsurface.texture = R_GetCurrentTexture(surface.texture);
11830         rsurface.lightmaptexture = NULL;
11831         rsurface.deluxemaptexture = NULL;
11832         rsurface.uselightmaptexture = false;
11833         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11834 }
11835
11836 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)
11837 {
11838         static msurface_t surface;
11839         const msurface_t *surfacelist = &surface;
11840
11841         // fake enough texture and surface state to render this geometry
11842         surface.texture = texture;
11843         surface.num_triangles = numtriangles;
11844         surface.num_firsttriangle = firsttriangle;
11845         surface.num_vertices = numvertices;
11846         surface.num_firstvertex = firstvertex;
11847
11848         // now render it
11849         rsurface.texture = R_GetCurrentTexture(surface.texture);
11850         rsurface.lightmaptexture = NULL;
11851         rsurface.deluxemaptexture = NULL;
11852         rsurface.uselightmaptexture = false;
11853         R_DrawModelTextureSurfaceList(1, &surfacelist, writedepth, prepass);
11854 }